【发布时间】:2011-09-27 08:19:49
【问题描述】:
我的需要是, 我的所有大部分活动都需要用户的位置来获取基于位置的更新数据。因此,我没有在所有活动中单独定义,而是定义了一个基本活动(BaseActivity.java)并声明所有活动都必须继承这个类。
例如:
package com.example;
import com.example.tools.Utilities;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.Window;
public class BaseActivity extends Activity {
protected static final String GpsTag = "GPS";
private static LocationManager mLocManager;
private static LocationListener mLocListener;
private static double mDefaultLatitude = 41.0793;
private static double mDefaultLongtitude = 29.0461;
private Location CurrentBestLocation;
private float mMinDistanceForGPSProvider = 200;
private float mMinDistanceForNetworkProvider = 1000;
private float mMinDistanceForPassiveProvider = 3000;
private long mMinTime = 0;
private UserLocation mCurrentLocation = new UserLocation(mDefaultLatitude,
mDefaultLongtitude);
private Boolean showLocationNotification = false;
protected Activity mActivity;
private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
UserManagement.logOut(getApplication());
Utilities.setApplicationTitle(mActivity);
// finish();
}
};
private BroadcastReceiver mLoggedInReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Utilities.setApplicationTitle(mActivity);
// finish();
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.registerReceiver(mLoggedOutReceiver, new IntentFilter(
Utilities.LOG_OUT_ACTION));
super.registerReceiver(mLoggedInReceiver, new IntentFilter(
Utilities.LOG_IN_ACTION));
mActivity = this;
if (mLocManager == null || mLocListener == null) {
mLocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mLocListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i(GpsTag, "Location Changed");
if (isBetterLocation(location, CurrentBestLocation)) {
sendBroadcast(new Intent(
Utilities.LOCATION_CHANGED_ACTION));
mCurrentLocation.Latitude = location.getLatitude();
mCurrentLocation.Longtitude = location.getLongitude();
if (location.hasAccuracy()) {
mCurrentLocation.Accuracy = location.getAccuracy();
}
UserManagement.UserLocation = mCurrentLocation;
mCurrentLocation.Latitude = location.getLatitude();
mCurrentLocation.Longtitude = location.getLongitude();
if (location.hasAccuracy()) {
mCurrentLocation.Accuracy = location.getAccuracy();
}
UserManagement.UserLocation = mCurrentLocation;
CurrentBestLocation = location;
}
}
@Override
public void onProviderDisabled(String provider) {
chooseProviderAndSetLocation();
}
@Override
public void onProviderEnabled(String provider) {
chooseProviderAndSetLocation();
}
@Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
};
chooseProviderAndSetLocation();
}
}
private void chooseProviderAndSetLocation() {
Location loc = null;
if (mLocManager == null)
return;
mLocManager.removeUpdates(mLocListener);
if (mLocManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
loc = mLocManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
} else if (mLocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
loc = mLocManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
for (String providerName : mLocManager.getProviders(true)) {
float minDistance = mMinDistanceForPassiveProvider;
if (providerName.equals("network"))
minDistance = mMinDistanceForNetworkProvider;
else if (providerName.equals("gps"))
minDistance = mMinDistanceForGPSProvider;
mLocManager.requestLocationUpdates(providerName, mMinTime,
minDistance, mLocListener);
Log.i(GpsTag, providerName + " listener binded...");
}
if (loc != null) {
if (mCurrentLocation == null)
mCurrentLocation = new UserLocation(mDefaultLatitude,
mDefaultLongtitude);
mCurrentLocation.Latitude = loc.getLatitude();
mCurrentLocation.Longtitude = loc.getLongitude();
mCurrentLocation.Accuracy = loc.hasAccuracy() ? loc.getAccuracy()
: 0;
UserManagement.UserLocation = mCurrentLocation;
CurrentBestLocation = loc;
} else {
if (showLocationNotification) {
Utilities
.warnUserWithToast(
getApplication(),
"Default Location");
}
UserManagement.UserLocation = new UserLocation(mDefaultLatitude,
mDefaultLongtitude);
}
}
private static final int TWO_MINUTES = 1000 * 60 * 2;
protected boolean isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use
// the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be
// worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same providerl
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
@Override
public boolean moveTaskToBack(boolean nonRoot) {
Utilities.warnUserWithToast(getApplicationContext(), "moveTaskToBack: " + nonRoot);
return super.moveTaskToBack(nonRoot);
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocManager.removeUpdates(mLocListener);
super.unregisterReceiver(mLoggedOutReceiver);
super.unregisterReceiver(mLoggedInReceiver);
}
@Override
protected void onRestart() {
super.onRestart();
Utilities.warnUserWithToast(getApplicationContext(), "onRestart: " + getPackageName());
}
@Override
protected void onPause() {
super.onPause();
mLocManager.removeUpdates(mLocListener);
Utilities.warnUserWithToast(getApplicationContext(), "onPause: " + getPackageName());
}
@Override
protected void onResume() {
super.onResume();
Utilities.warnUserWithToast(getApplicationContext(), "onResume: " );
chooseProviderAndSetLocation();
}
@Override
protected void finalize() throws Throwable {
Utilities.warnUserWithToast(getApplicationContext(), "finalize: " );
super.finalize();
}
@Override
protected void onPostResume() {
Utilities.warnUserWithToast(getApplicationContext(), "onPostResume: ");
super.onPostResume();
}
@Override
protected void onStart() {
Utilities.warnUserWithToast(getApplicationContext(), "onStart: " );
super.onStart();
}
@Override
protected void onStop() {
Utilities.warnUserWithToast(getApplicationContext(), "onStop: ");
super.onStop();
}
public void setLocationNotification(Boolean show) {
this.showLocationNotification = show;
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
if (menu != null && UserManagement.CurrentUser != null) {
final MenuItem miExit = menu.add("Log Out");
miExit.setIcon(R.drawable.menu_exit);
miExit.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
sendBroadcast(new Intent(Utilities.LOG_OUT_ACTION));
menu.removeItem(miExit.getItemId());
return true;
}
});
}
return super.onCreateOptionsMenu(menu);
}
}
public class MainActivity extends BaseActivity {
}
这使得获取管理常用事件处理,例如LocationManager,onCreateOptionsMenu
效果很好。但是有一个小问题。 onPause,onResume,onRestart 我绑定和取消绑定 locationlistener 事件,所以 Gps 有时没有足够的时间来抛出 locationchanged 事件,因为用户可以在活动之间快速传递,并且 GPS 有绑定和取消绑定事件。所以我将我的 LocationManager 和 LocationListener 变量设置为静态的。现在它很完美。在所有活动中,我都有用户的最新位置。这很棒!但是 GPS 一直在运行。
这是我想要的东西,我如何知道用户将应用程序发送回。我的意思是退出或暂停它。
P.S:onPause、onResume 事件在所有活动中运行。我需要有关整个应用程序的一般信息。
【问题讨论】:
标签: android gps memory-management