我正在尝试制作一个应用程序,通过跟踪屏幕锁定和解锁时间来监控用户的手机使用情况。我尝试设置一个 BroadcastReceiver
,当应用程序在后台运行时它可以正常工作。但是当我关闭应用程序时将不起作用。有解决办法吗?
我现在使用的代码如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, ScreenListenerService.class);
startService(intent);
}
}
ScreenListenerService
类如下..
public class ScreenListenerService extends Service {
private BroadcastReceiver mScreenStateBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// Save something to the server
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// Save something to the server
}
}
};
@Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenStateBroadcastReceiver, intentFilter);
}
@Override
public void onDestroy() {
unregisterReceiver(mScreenStateBroadcastReceiver);
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
我的AndroidManifest
文件如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abbinvarghese.calculu">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service android:name=".ScreenListenerService" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
最佳答案
要克服 8.0 的强加限制,您可以运行前台服务。就像服务一样,但通知会发布到前台。
那么服务代码是这样的(记得在Destory上注销receiver):
BroadcastReceiver screenReceiver;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startRunningInForeground();
detectingDeterminateOfServiceCall(intent.getExtras());
registerBroadcastReceivers();
return START_STICKY;
}
private void startRunningInForeground() {
//if more than or equal to 26
if (Build.VERSION.SDK_INT >= 26) {
//if more than 26
if(Build.VERSION.SDK_INT > 26){
String CHANNEL_ONE_ID = "sensor.example. geyerk1.inspect.screenservice";
String CHANNEL_ONE_NAME = "Screen service";
NotificationChannel notificationChannel = null;
notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.createNotificationChannel(notificationChannel);
}
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.background_running);
Notification notification = new Notification.Builder(getApplicationContext())
.setChannelId(CHANNEL_ONE_ID)
.setContentTitle("Recording data")
.setContentText("ActivityLog is logging data")
.setSmallIcon(R.drawable.background_running)
.setLargeIcon(icon)
.build();
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
notification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
startForeground(101, notification);
}
//if version 26
else{
startForeground(101, updateNotification());
}
}
//if less than version 26
else{
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Activity logger")
.setContentText("data recording on going")
.setSmallIcon(R.drawable.background_running)
.setOngoing(true).build();
startForeground(101, notification);
}
}
private Notification updateNotification() {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
return new NotificationCompat.Builder(this)
.setContentTitle("Activity log")
.setTicker("Ticker")
.setContentText("recording of data is on going")
.setSmallIcon(R.drawable.activity_log_icon)
.setContentIntent(pendingIntent)
.setOngoing(true).build();
}
private void detectingDeterminateOfServiceCall(Bundle b) {
if(b != null){
Log.i("screenService", "bundle not null");
if(b.getBoolean("phone restarted")){
storeInternally("Phone restarted");
}
}else{
Log.i("screenService", " bundle equals null");
}
documentServiceStart();
}
private void documentServiceStart() {
Log.i("screenService", "started running");
}
private void registerBroadcastReceivers() {
screenReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (Objects.requireNonNull(intent.getAction())){
case Intent.ACTION_SCREEN_ON:
//or do something else
storeInternally("Screen on");
break;
case Intent.ACTION_SCREEN_OFF:
//or do something else
storeInternally("Screen off");
break;
}
}
};
IntentFilter screenFilter = new IntentFilter();
screenFilter.addAction(Intent.ACTION_SCREEN_ON);
screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenReceiver, screenFilter);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenReceiver);
}
并从主要 Activity 中调用它:
private void startServiceRunning() {
if(!isMyServiceRunning(Background.class)){
if(Build.VERSION.SDK_INT >25){
startForegroundService(new Intent(this, Background.class));
}else{
startService(new Intent(this, Background.class));
}
}
}
关于java - SCREEN_ON 和 SCREEN_OFF 的 BroadcastReceiver,即使在退出应用程序后也是如此,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51324659/