BroadcastReceiver用于“USER_PRESENT”泄漏内存

时间:2017-03-20 12:35:15

标签: android service memory-leaks broadcastreceiver unlock

我有一个包含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);
    }
}

1 个答案:

答案 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();
    }
}}