这里是我在Android API 26(Oreo)及以上版本中监听SCREEN_OFF和SCREEN_ON广播所做的事情。这个答案与小部件无关,但可能有助于找到一些解决方法。
我正在使用作业调度器来注册和取消注册广播接收器,以便监听SCREEN_OFF和SCREEN_ON操作。
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import android.util.Log;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import java.util.concurrent.TimeUnit;
public class LockScreenJob extends Job {
private static final String TAG = LockScreenJob.class.getSimpleName();
public static final String TAG_P = "periodic_job_tag";
public static final String TAG_I = "immediate_job_tag";
public static UnlockReceiver aks_Receiver = null;
@Override
@NonNull
protected Result onRunJob(Params params) {
String jobTag = params.getTag();
if (BuildConfig.DEBUG) {
Log.i(TAG, "Job started! " + jobTag);
}
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
boolean isInteractive = false;
if (Build.VERSION.SDK_INT >= 20) {
isInteractive = pm.isInteractive();
} else {
isInteractive = pm.isScreenOn();
}
try {
if (aks_Receiver != null) {
getContext().getApplicationContext().unregisterReceiver(aks_Receiver);
}
} catch (Exception e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
} finally {
aks_Receiver = null;
}
try {
IntentFilter filter = new IntentFilter("android.intent.action.SCREEN_OFF");
filter.addAction("android.intent.action.SCREEN_ON");
aks_Receiver = new UnlockReceiver();
getContext().getApplicationContext().registerReceiver(aks_Receiver, filter);
} catch (Exception e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
}
if (isInteractive)
{
}
return Result.SUCCESS;
}
public static int scheduleJobPeriodic() {
int jobId = new JobRequest.Builder(TAG_P)
.setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5))
.setRequiredNetworkType(JobRequest.NetworkType.ANY)
.build()
.schedule();
return jobId;
}
public static int runJobImmediately() {
int jobId = new JobRequest.Builder(TAG_I)
.startNow()
.build()
.schedule();
return jobId;
}
public static void cancelJob(int jobId) {
JobManager.instance().cancel(jobId);
}
}
我的JobCrator类
LockScreenJobCreator是:
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobCreator;
public class LockScreenJobCreator implements JobCreator {
@Override
@Nullable
public Job create(@NonNull String tag) {
switch (tag) {
case LockScreenJob.TAG_I:
return new LockScreenJob();
case LockScreenJob.TAG_P:
return new LockScreenJob();
default:
return null;
}
}
}
广播接收器类 UnlockReceiver 是:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class UnlockReceiver extends BroadcastReceiver {
private static final String TAG = UnlockReceiver.class.getSimpleName();
@Override
public void onReceive(Context appContext, Intent intent) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "onReceive: " + intent.getAction());
}
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_OFF))
{
} else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_ON)) {
}
}
}
英译中:
并将 JobCreator 类添加到 Application 类,如下所示:
public class AksApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
JobManager.create(this).addJobCreator(new LockScreenJobCreator());
}
}
不要忘记在你的 AndroidManifest.xml 中定义应用程序类。
之后,我会像这样从我的 Activity 中启动 Job 调度器:
import android.support.v7.app.AppCompatActivity;
public class LockScreenActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
runJobScheduler();
}
@Override
protected void onStop() {
super.onStop();
cancelImmediateJobScheduler();
}
private void runJobScheduler() {
Set<JobRequest> jobSets_I = null, jobSets_P = null;
try {
jobSets_I = JobManager.instance().getAllJobRequestsForTag(LockScreenJob.TAG_I);
jobSets_P = JobManager.instance().getAllJobRequestsForTag(LockScreenJob.TAG_P);
if (jobSets_I == null || jobSets_I.isEmpty()) {
LockScreenJob.runJobImmediately();
}
if (jobSets_P == null || jobSets_P.isEmpty()) {
LockScreenJob.scheduleJobPeriodic();
}
if (jobSets_P != null && jobSets_P.size() > 2) {
JobManager.instance().cancelAllForTag(LockScreenJob.TAG_P);
}
} catch (Exception e) {
if (Global_Var.isdebug) {
e.printStackTrace();
}
} finally {
if (jobSets_I != null) {
jobSets_I.clear();
}
if (jobSets_P != null) {
jobSets_P.clear();
}
jobSets_I = jobSets_P = null;
}
}
private void cancelImmediateJobScheduler() {
JobManager.instance().cancelAllForTag(LockScreenJob.TAG_I);
}
}
通过这样运行作业调度器,我可以在不运行任何前台或后台服务的情况下监听SCREEN_OFF和SCREEN_ON操作。我在API 26+上测试了上述代码,它可以正常工作。