package com.qmusic.common;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
import android.content.Context;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import com.qmusic.MyApplication;
import com.qmusic.uitls.BLog;
public class BLocationManager implements LocationListener {
static final String TAG = BLocationManager.class.getSimpleName();
public static final int STATUS_NOT_DEF = 0;
public static final int STATUS_READY = 1;
public static final int STATUS_DOING = 2;
public static final int STATUS_DONE = 3;
public static final int STATUS_FAILED = 4;
private LocationManager locationManager;
private String bestProvider = "";
private Location location;
private int mState = STATUS_NOT_DEF;
static private BLocationManager instance;
private Context mContext;
WeakHashMap<IAsyncDataCallback, String> callbackList;
long lastupdateTime;
private BLocationManager(Context ctx) {
mContext = ctx;
locationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
callbackList = new WeakHashMap<IAsyncDataCallback, String>();
List<String> providers = locationManager.getAllProviders();
if (providers != null) {
BLog.i(TAG, "AllProviders:" + providers.toString());
}
bestProvider = getBestProvider();
if (!TextUtils.isEmpty(bestProvider)) {
BLog.i(TAG, "BEST Provider:" + bestProvider);
location = locationManager.getLastKnownLocation(bestProvider);
if (location != null) {
BLog.i(TAG, "LastKnownLocation : " + location.toString());
}
} else {
BLog.e(TAG, "LocationManager init failed. bestProvider = " + bestProvider);
}
}
public static void init(Context c) {
if (instance == null) {
instance = new BLocationManager(c);
}
}
public static BLocationManager getInstance() {
return instance;
}
/**
*
* @param callback
* @param millis
* use cache if lastKnowLocation is in millis
*/
public void updateLocation(final IAsyncDataCallback callback, final long millis) {
if (System.currentTimeMillis() - lastupdateTime <= millis && location != null) {
MyApplication.post(new Runnable() {
@Override
public void run() {
callback.callback(BConstants.MSG_RESULT_OK, location);
}
});
} else {
bestProvider = getBestProvider();
if (TextUtils.isEmpty(bestProvider)) {
checkCallback(BConstants.MSG_RESULT_FAILED);
return;
}
callbackList.put(callback, "");
if (mState == STATUS_DOING) {
return;
}
BLog.i(TAG, "updateLocation BEST Provider : " + bestProvider);
mState = STATUS_DOING;
MyApplication.postDelayed(timeCheck, 10000);
BLog.i(TAG, "requestLocationUpdates. bestProvider = " + bestProvider);
locationManager.requestLocationUpdates(bestProvider, 2000, 500, this);
}
}
public Location getLastKnowLocation() {
return location;
}
/**
* format(lat,lng)
*
* @return
*/
public String getLatLng() {
String laglng = null;
if (location != null) {
StringBuilder sb = new StringBuilder();
sb.append(location.getLatitude());
sb.append(",");
sb.append(location.getLongitude());
laglng = sb.toString();
}
return laglng;
}
public void getLocationName(final IAsyncDataCallback callback) {
final AsyncTask<Void, Void, String[]> asyncTask = new AsyncTask<Void, Void, String[]>() {
@Override
protected String[] doInBackground(Void... params) {
String[] names = getLocationName(location);
return names;
}
@Override
protected void onPostExecute(String result[]) {
if (result != null && result.length > 0) {
callback.callback(BConstants.MSG_RESULT_OK, result);
} else {
callback.callback(BConstants.MSG_RESULT_FAILED, null);
}
}
};
if (location == null) {
updateLocation(new IAsyncDataCallback() {
@Override
public void callback(int result, Object data) {
if (result == BConstants.MSG_RESULT_OK) {
asyncTask.execute();
} else {
callback.callback(BConstants.MSG_RESULT_FAILED, null);
}
}
}, 0);
} else {
asyncTask.execute();
}
}
private String getBestProvider() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setPowerRequirement(Criteria.POWER_LOW);
String prov = locationManager.getBestProvider(criteria, true);
return prov;
}
Runnable timeCheck = new Runnable() {
@Override
public void run() {
BLog.i(TAG, "UpdateLocation timeout. mState = " + mState);
if (mState == STATUS_DOING) {
mState = STATUS_FAILED;
BLog.i(TAG, "onLocationChanged: location failed");
checkCallback(BConstants.MSG_RESULT_FAILED);
}
}
};
private void checkCallback(final int result) {
Set<IAsyncDataCallback> cs = callbackList.keySet();
for (IAsyncDataCallback c : cs) {
try {
c.callback(result, location);
} catch (Exception ex) {
ex.printStackTrace();
}
}
callbackList.clear();
}
private void stop() {
mState = STATUS_READY;
locationManager.removeUpdates(instance);
}
@Override
public void onLocationChanged(Location arg0) {
if (arg0 == null) {
mState = STATUS_FAILED;
BLog.i(TAG, "onLocationChanged: location failed");
checkCallback(BConstants.MSG_RESULT_FAILED);
} else {
mState = STATUS_DONE;
location = arg0;
lastupdateTime = System.currentTimeMillis();
BLog.i(TAG, "onLocationChanged:" + arg0.toString());
checkCallback(BConstants.MSG_RESULT_OK);
}
stop();
}
@Override
public void onProviderDisabled(String provider) {
BLog.d(TAG, "onProviderDisabled : " + provider);
if (provider.equals(bestProvider)) {
// location = null;
mState = STATUS_FAILED;
checkCallback(BConstants.MSG_RESULT_FAILED);
stop();
}
}
@Override
public void onProviderEnabled(String provider) {
BLog.d(TAG, "onProviderEnabled : " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
BLog.d(TAG, "onStatusChanged : " + provider + " : " + status);
if (provider.equals(bestProvider) && (status == LocationProvider.OUT_OF_SERVICE || status == LocationProvider.TEMPORARILY_UNAVAILABLE)) {
BLog.v(TAG, "Provider: " + bestProvider + " become unavailable.");
// location = null;
mState = STATUS_FAILED;
checkCallback(BConstants.MSG_RESULT_FAILED);
stop();
}
}
private String[] getLocationName(Location location) {
try {
Geocoder geocoder = new Geocoder(mContext);
List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
if (addresses != null && addresses.size() > 0) {
String[] addressStrs = new String[addresses.size()];
for (int j = 0; j < addresses.size(); j++) {
Address address = addresses.get(j);
StringBuffer sb = new StringBuffer();
for (int i = 0; i <= address.getMaxAddressLineIndex(); i++) {
sb.append(address.getAddressLine(i) + " ");
}
addressStrs[j] = sb.toString();
}
return addressStrs;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return new String[0];
}
}