У меня есть приложение, содержащее Activity A, Service S и BroadcastReceiver BR. Я хочу, чтобы приложение слушало, когда пользователь разблокирует телефон. В настоящее время это достигается за счет того, что A запускает S и привязывается к нему. S запустится и зарегистрирует BR для прослушивания «android.intent.action.USER_PRESENT».
Теоретически приложение должно иметь возможность бесконечно прослушивать разблокировку телефона в фоновом режиме. Мое приложение выполняет свою задачу, но я вижу в мониторе Android, что использование памяти неуклонно увеличивается и будет увеличиваться примерно на 0,033 МБ для каждой разблокировки (каждый раз, когда вызывается 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());
}
}
Статус разблокировки:
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);
}
}