我有一个包含Activity A,Service S和BroadcastReceiver BR的应用程序。我希望应用程序做的是在用户解锁手机时收听。目前,这是通过启动A并绑定它来实现的。 S将启动并注册BR以侦听“android.intent.action.USER_PRESENT”。
理论上,应用程序应该能够在后台无限期地侦听手机解锁。我的应用程序完成了它的目的,但我在Android监视器中看到内存使用量稳步增加,并且每次解锁时都会增加大约0,033MB(每次调用onReceive(?))。
以下是代码。
的活动:
public class MainActivity extends Activity implements BackgroundService.ServiceCallbacks
{
private TextView lastUnlock;
private boolean isBound = false;
private BackgroundService backgroundService;
private ServiceConnection serviceConnection = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
BackgroundService.LocalBinder binder = (BackgroundService.LocalBinder) service;
backgroundService = binder.getServiceInstance();
backgroundService.registerActivity(MainActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
isBound = false;
backgroundService = null;
}
};
/** Activity is created, start service and bind to it **/
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lastUnlock = (TextView) findViewById(R.id.lastUnlock_TW);
Intent serviceIntent = new Intent(this, BackgroundService.class);
startService(serviceIntent);
bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
isBound = true;
}
/** Activity is destroyed, it should unbind from the service **/
@Override
protected void onDestroy()
{
super.onDestroy();
if (isBound)
{
backgroundService.unregisterActivity();
unbindService(serviceConnection);
isBound = false;
}
}
/** The service can call this method to update the lastUnlock TextView **/
@Override
public void updateClient(String data)
{
lastUnlock.setText(data);
}
}
服务:
public class BackgroundService extends Service
{
ServiceCallbacks activity;
private final IBinder LOCAL_BINDER = new LocalBinder();
private UserPresentReceiver userPresentReceiver;
SharedPreferences sharedPreferences;
/** The service is created, receivers are registered here **/
@Override
public void onCreate()
{
super.onCreate();
userPresentReceiver = new UserPresentReceiver();
registerReceiver(userPresentReceiver, new IntentFilter("android.intent.action.USER_PRESENT"));
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
}
/** An activity called startService() or the process was killed, returning START_STICKY
** which restarts the service and this method is called **/
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
/** An activity just bound to the service **/
@Override
public IBinder onBind(Intent intent)
{
return LOCAL_BINDER;
}
/** Service is destroyed, unregister the receivers **/
@Override
public void onDestroy()
{
super.onDestroy();
unregisterReceiver(userPresentReceiver);
}
/** **/
public class LocalBinder extends Binder
{
public BackgroundService getServiceInstance()
{
return BackgroundService.this;
}
}
/** Update the activity if it is connected, and save the unlockStatus in the preferences **/
public void updateActivity(String unlockStatus)
{
if (activity != null)
{
this.activity.updateClient(unlockStatus);
}
SharedPreferences.Editor spEditor = sharedPreferences.edit();
spEditor.putString("saved_last_unlock", unlockStatus);
spEditor.apply();
}
/** Methods an activity can call to register or unregister itself to the service **/
public void registerActivity(Activity activity)
{
this.activity = (ServiceCallbacks) activity;
// If the last unlock is saved in the preferences, retrieve it from there
String savedLastUnlock = sharedPreferences.getString("saved_last_unlock", null);
if (savedLastUnlock != null)
{
this.activity.updateClient(savedLastUnlock);
}
}
public void unregisterActivity()
{
activity = null;
}
/** An activity has to implement this interface so that the service can send commands to it **/
public interface ServiceCallbacks
{
void updateClient(String data);
}
}
广播接收器:
public class UserPresentReceiver extends BroadcastReceiver
{
private final String TAG = "UserPresentReceiver";
UnlockStatus unlockStatus;
public UserPresentReceiver()
{
unlockStatus = new UnlockStatus();
}
@Override
public void onReceive(Context context, Intent intent)
{
unlockStatus.setStatus(new Date());
BackgroundService service = (BackgroundService) context;
service.updateActivity(unlockStatus.getStatus());
}
}
UnlockStatus:
public class UnlockStatus
{
private Calendar calendar;
private final SimpleDateFormat SDF = new SimpleDateFormat("dd.MM.yyyy' kl. 'HH:mm:ss");
private boolean unlockRegistered = false;
public UnlockStatus()
{
calendar = Calendar.getInstance();
}
public String getStatus()
{
if (unlockRegistered)
return SDF.format(calendar.getTime());
else
return null;
}
public void setStatus(Date date)
{
unlockRegistered = true;
calendar.setTime(date);
}
}
答案 0 :(得分:0)
请找到解决方案
public class MyApplication extends Application implements HM_Constants, Application.ActivityLifecycleCallbacks, ComponentCallbacks2 {
public static String stateOfLifeCycle = "";
public static boolean wasInBackground = false;
private static HydratemateApplication mInstance;
private static String TAG = HydratemateApplication.class.getName();
boolean status;
ScreenOffReceiver screenOffReceiver = new ScreenOffReceiver();
public static synchronized HydratemateApplication getInstance() {
return mInstance;
}
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
registerActivityLifecycleCallbacks(this);
registerReceiver(screenOffReceiver, new IntentFilter("android.intent.action.SCREEN_OFF"));
// new HM_PrefsManager(mInstance).save(Prefs_Keys.SERVICE_THREAD_STOP,"NO");
}
@Override
public void onActivityCreated(Activity activity, Bundle arg1) {
// Log.d(TAG, "onActivityCreated " + activity.getLocalClassName());
wasInBackground = false;
status = false;
stateOfLifeCycle = "Create";
}
@Override
public void onActivityStarted(Activity activity) {
// Log.d(TAG, "onActivityStarted " + activity.getLocalClassName());
stateOfLifeCycle = "Start";
}
@Override
public void onActivityResumed(Activity activity) {
Log.d(TAG, "onActivityResumed " + activity.getLocalClassName());
stateOfLifeCycle = "Resume";
try {
Intent service = new Intent(getApplicationContext(), VolumeService.class);
stopService(service);
} catch (Exception e) {
e.printStackTrace();
}
try {
if (BatteryHealthActivity.mBluetoothLeForegroundService != null && status) {
//BatteryHealthActivity.mBluetoothLeForegroundService.indicateCharacteristic(UUID.fromString(GattAttributes.BATTERY_LEVEL_SERVICE_UUID), UUID.fromString(GattAttributes.BATTERY_LEVEL_CHARACTERSTIC_UUID), true);
status = false;
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onActivityPaused(Activity activity) {
// Log.d(TAG, "onActivityPaused " + activity.getLocalClassName());
stateOfLifeCycle = "Pause";
}
@Override
public void onActivityStopped(Activity activity) {
// Log.d(TAG, "onActivityStopped " + activity.getLocalClassName());
stateOfLifeCycle = "Stop";
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle arg1) {
//Log.d(TAG, "onActivitySaveInstanceState " + activity.getLocalClassName());
}
@Override
public void onActivityDestroyed(Activity activity) {
// Log.d(TAG, "onActivityDestroyed " + activity.getLocalClassName());
Log.d("iam", "calling");
wasInBackground = false;
stateOfLifeCycle = "Destroy";
}
@Override
public void onTrimMemory(int level) {
if (stateOfLifeCycle.equals("Stop")) {
wasInBackground = true;
}
super.onTrimMemory(level);
Log.d(TAG, "onTrimMemory " + level);
onBackground();
}
public void onBackground(){
if (!isMyServiceRunning(VolumeService.class)) {
try {
status = true;
if (BatteryHealthActivity.mBluetoothLeForegroundService != null) {
BatteryHealthActivity.mBluetoothLeForegroundService.indicateCharacteristic(UUID.fromString(GattAttributes.BATTERY_LEVEL_SERVICE_UUID), UUID.fromString(GattAttributes.BATTERY_LEVEL_CHARACTERSTIC_UUID), false);
}
new ForegroundCheckTask().execute(mInstance).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
class ScreenOffReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
wasInBackground = true;
onBackground();
}
}}