运行时权限
在应用间共享文件
计划排定作业
JobIntentService(android.support.v4.app.JobIntentService)
//build.gradle(project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
name 'AliYun Google Repository Proxy'
url 'https://maven.aliyun.com/repository/google'
}
maven {
name 'AliYun Jcenter Repository Proxy'
url 'https://maven.aliyun.com/repository/jcenter'
}
// google()
// jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven {
name 'AliYun Google Repository Proxy'
url 'https://maven.aliyun.com/repository/google'
}
maven {
name 'AliYun Jcenter Repository Proxy'
url 'https://maven.aliyun.com/repository/jcenter'
}
// google()
// jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.tomorrow.architetest"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-compat:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.architetest">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".TestJobIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
</application>
</manifest>
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
enqueueWork();
}
}, 60000);
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "zwm, onStart");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "zwm, onStop");
}
private void enqueueWork() {
Log.d(TAG, "zwm, enqueueWork, thread: " + Thread.currentThread().getName());
Intent intent = new Intent();
ComponentName componentName = new ComponentName(getApplicationContext(), TestJobIntentService.class);
intent.setComponent(componentName);
TestJobIntentService.enqueueWork(getApplicationContext(), intent);
}
}
//TestJobIntentService
public class TestJobIntentService extends JobIntentService {
private static final String TAG = "TestJobIntentService";
public static final int JOB_ID = 10;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, TestJobIntentService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
Log.d(TAG, "zwm, onHandleWork, thread: " + Thread.currentThread().getName());
}
}
//输出log
2019-11-22 09:35:23.960 19027-19027/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 09:35:25.683 19027-19027/com.tomorrow.architetest D/MainActivity: zwm, onStart
2019-11-22 09:35:27.400 19027-19027/com.tomorrow.architetest D/MainActivity: zwm, onStop
2019-11-22 09:36:25.326 19027-19027/com.tomorrow.architetest D/MainActivity: zwm, enqueueWork, thread: main
2019-11-22 09:36:25.625 19027-20173/com.tomorrow.architetest D/TestJobIntentService: zwm, onHandleWork, thread: AsyncTask #1
JobService(android.app.job.JobService)
深入理解JobScheduler与JobService的使用
例1:
//build.gradle(project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
name 'AliYun Google Repository Proxy'
url 'https://maven.aliyun.com/repository/google'
}
maven {
name 'AliYun Jcenter Repository Proxy'
url 'https://maven.aliyun.com/repository/jcenter'
}
// google()
// jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
maven {
name 'AliYun Google Repository Proxy'
url 'https://maven.aliyun.com/repository/google'
}
maven {
name 'AliYun Jcenter Repository Proxy'
url 'https://maven.aliyun.com/repository/jcenter'
}
// google()
// jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.tomorrow.architetest"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.architetest">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".TestJobService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
</application>
</manifest>
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
TestJobService.scheduleJob(getApplicationContext());
}
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "zwm, onStart");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "zwm, onStop");
}
}
//TestJobService
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class TestJobService extends JobService {
private static final String TAG = "TestJobService";
private static final int JOB_ID = 20;
private static final long REPEAT_TIME = 30 * 60 * 1000;
@Override
public boolean onStartJob(JobParameters params) {
Log.d(TAG, "zwm, onStartJob, thread: " + Thread.currentThread().getName());
return false; //返回false表示任务已经全部做完,系统会解绑JobService,并回调onDestroy()方法。
}
@Override
public boolean onStopJob(JobParameters params) {
Log.d(TAG, "zwm, onStopJob, thread: " + Thread.currentThread().getName());
return false;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "zwm, onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "zwm, onDestroy");
}
public static void scheduleJob(Context context) {
Log.d(TAG, "zwm, scheduleJob REPEAT_TIME: " + REPEAT_TIME + ", thread: " + Thread.currentThread().getName());
ComponentName serviceName = new ComponentName(context, TestJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceName);
builder .setPeriodic(REPEAT_TIME)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false);
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
if(jobScheduler != null) {
int ret = jobScheduler.schedule(builder.build());
if (ret < 0) {
Log.d(TAG, "zwm, schedule fail");
} else {
Log.d(TAG, "zwm, schedule success");
}
}
}
}
//输出log(路径:断网 -> 启动MainActivity -> 连接WIFI -> Check)
2019-11-22 13:49:25.373 29377-29377/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 13:49:25.505 29377-29377/com.tomorrow.architetest D/TestJobService: zwm, scheduleJob REPEAT_TIME: 1800000, thread: main
2019-11-22 13:49:25.522 29377-29377/com.tomorrow.architetest D/TestJobService: zwm, schedule success
2019-11-22 13:49:25.529 29377-29377/com.tomorrow.architetest D/MainActivity: zwm, onStart
2019-11-22 13:49:45.599 29377-29377/com.tomorrow.architetest D/TestJobService: zwm, onCreate //连接WIFI后系统启动JobService
2019-11-22 13:49:45.613 29377-29377/com.tomorrow.architetest D/TestJobService: zwm, onStartJob, thread: main
2019-11-22 13:49:45.679 29377-29377/com.tomorrow.architetest D/TestJobService: zwm, onDestroy
例2:
//TestJobService
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class TestJobService extends JobService {
private static final String TAG = "TestJobService";
private static final int JOB_ID = 20;
private static final long REPEAT_TIME = 30 * 60 * 1000;
private JobParameters mJobParameters;
@Override
public boolean onStartJob(JobParameters params) {
Log.d(TAG, "zwm, onStartJob, thread: " + Thread.currentThread().getName());
mJobParameters = params;
new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "zwm, run, thread: " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
jobFinished(mJobParameters, false);
Log.d(TAG, "zwm, call jobFinished, thread: " + Thread.currentThread().getName());
}
}).start();
return true; //返回true表示任务已经启动成功,但还没有全部做完,此时可以在任务完成后,应用自行调用jobFinished方法。
}
@Override
public boolean onStopJob(JobParameters params) {
Log.d(TAG, "zwm, onStopJob, thread: " + Thread.currentThread().getName());
return false;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "zwm, onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "zwm, onDestroy");
}
public static void scheduleJob(Context context) {
Log.d(TAG, "zwm, scheduleJob REPEAT_TIME: " + REPEAT_TIME + ", thread: " + Thread.currentThread().getName());
ComponentName serviceName = new ComponentName(context, TestJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceName);
builder .setPeriodic(REPEAT_TIME)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(false);
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
if(jobScheduler != null) {
int ret = jobScheduler.schedule(builder.build());
if (ret < 0) {
Log.d(TAG, "zwm, schedule fail");
} else {
Log.d(TAG, "zwm, schedule success");
}
}
}
}
//输出log(路径:连接WIFI -> 启动MainActivity -> Check)
2019-11-22 14:07:31.504 31854-31854/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 14:07:31.629 31854-31854/com.tomorrow.architetest D/TestJobService: zwm, scheduleJob REPEAT_TIME: 1800000, thread: main
2019-11-22 14:07:31.708 31854-31854/com.tomorrow.architetest D/TestJobService: zwm, schedule success
2019-11-22 14:07:32.314 31854-31854/com.tomorrow.architetest D/MainActivity: zwm, onStart
2019-11-22 14:07:32.450 31854-31854/com.tomorrow.architetest D/TestJobService: zwm, onCreate
2019-11-22 14:07:32.864 31854-31854/com.tomorrow.architetest D/TestJobService: zwm, onStartJob, thread: main
2019-11-22 14:07:32.865 31854-32012/com.tomorrow.architetest D/TestJobService: zwm, run, thread: Thread-6
2019-11-22 14:07:37.867 31854-32012/com.tomorrow.architetest D/TestJobService: zwm, call jobFinished, thread: Thread-6
2019-11-22 14:07:38.295 31854-31854/com.tomorrow.architetest D/TestJobService: zwm, onDestroy
后台执行限制
后台服务限制
targetSdkVersion为Android O的前台应用可以自由地运行前台和后台服务。当应用进入后台之后,它仍然有几分钟的时间窗口来启动和运行服务。当这个时间窗口到期时,应用就进入空闲状态,系统将停止应用的后台服务运行。
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.tomorrow.architetest"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-compat:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.architetest">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BgService"/>
</application>
</manifest>
//BgService
public class BgService extends Service {
private static final String TAG = "BgService";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "zwm, onCreate");
}
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "zwm, run");
Intent intent = new Intent(MainActivity.this, BgService.class);
startService(intent);
}
}, 5 * 60 * 1000);
}
}
//输出log
2019-11-22 18:34:51.419 29451-29451/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 18:39:51.926 29451-29451/com.tomorrow.architetest D/MainActivity: zwm, run
java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.tomorrow.architetest/.BgService }: app is in background uid UidRecord{5372469 u0a413 LAST bg:+4m58s165ms idle change:idle procs:1 proclist:29451, seq(0,0,0)}
静态注册隐式广播限制
targetSdkVersion为Android O的应用不允许在Manifest文件中注册隐式广播。隐式广播是指不会定向发送的广播。
例1:静态注册隐式广播限制
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.tomorrow.architetest"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-compat:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.architetest">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".TestBroadcastReceiver">
<intent-filter>
<action android:name="com.tomorrow.broadcast"/>
</intent-filter>
</receiver>
</application>
</manifest>
//TestBroadcastReceiver
public class TestBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "TestBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "zwm, onReceive, this: " + this);
}
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("com.tomorrow.broadcast");
sendBroadcast(intent);
Log.d(TAG, "zwm, sendBroadcast");
}
}
//输出log
2019-11-22 18:56:33.578 7720-7720/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 18:56:33.683 7720-7720/com.tomorrow.architetest D/MainActivity: zwm, sendBroadcast
例2:静态注册隐式广播适配
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("com.tomorrow.broadcast");
intent.setPackage(getPackageName()); //增加这一句则可以接受隐式广播
sendBroadcast(intent);
Log.d(TAG, "zwm, sendBroadcast");
}
}
//输出log
2019-11-22 19:13:46.667 11730-11730/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 19:13:46.720 11730-11730/com.tomorrow.architetest D/MainActivity: zwm, sendBroadcast
2019-11-22 19:13:46.761 11730-11730/com.tomorrow.architetest D/TestBroadcastReceiver: zwm, onReceive, this: com.tomorrow.architetest.TestBroadcastReceiver@1a697b3
例3:动态注册隐式广播
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.architetest">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".TestBroadcastReceiver"/> //不需要<intent-filter>
</application>
</manifest>
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TestBroadcastReceiver mTestBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
mTestBroadcastReceiver = new TestBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.tomorrow.broadcast");
registerReceiver(mTestBroadcastReceiver, intentFilter);
Intent intent = new Intent();
intent.setAction("com.tomorrow.broadcast");
sendBroadcast(intent);
Log.d(TAG, "zwm, sendBroadcast");
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mTestBroadcastReceiver);
}
}
//输出log
2019-11-22 19:21:36.673 15609-15609/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 19:21:37.207 15609-15609/com.tomorrow.architetest D/MainActivity: zwm, sendBroadcast
2019-11-22 19:21:37.609 15609-15609/com.tomorrow.architetest D/TestBroadcastReceiver: zwm, onReceive, this: com.tomorrow.architetest.TestBroadcastReceiver@58774b0
例4:动态注册隐式广播(使用本地广播)
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.architetest">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".TestBroadcastReceiver"/>
</application>
</manifest>
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TestBroadcastReceiver mTestBroadcastReceiver;
private LocalBroadcastManager mLocalBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(getApplicationContext());
mTestBroadcastReceiver = new TestBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.tomorrow.broadcast");
mLocalBroadcastManager.registerReceiver(mTestBroadcastReceiver, intentFilter);
Intent intent = new Intent();
intent.setAction("com.tomorrow.broadcast");
mLocalBroadcastManager.sendBroadcast(intent);
Log.d(TAG, "zwm, sendBroadcast");
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocalBroadcastManager.unregisterReceiver(mTestBroadcastReceiver);
}
}
//输出log
2019-11-22 19:50:11.196 20978-20978/com.tomorrow.architetest D/MainActivity: zwm, onCreate
2019-11-22 19:50:11.301 20978-20978/com.tomorrow.architetest D/MainActivity: zwm, sendBroadcast
2019-11-22 19:50:11.341 20978-20978/com.tomorrow.architetest D/TestBroadcastReceiver: zwm, onReceive, this: com.tomorrow.architetest.TestBroadcastReceiver@58774b0
提醒窗口
targetSdkVersion在Android 7.0及以下:
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.tomorrow.androidtest1"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.androidtest1">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<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">
<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>
//MainActivity
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
showSystemDialog();
}
}, 10000);
}
private void showSystemDialog() {
Log.d(TAG, "zwm, showSystemDialog");
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setTitle("Dialog")
.setMessage("Message")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); //TYPE_SYSTEM_ALERT
dialog.show();
}
}
//输出log
11-23 11:41:14.271 20909-20909/com.tomorrow.androidtest1 D/MainActivity: zwm, onCreate
11-23 11:41:24.476 20909-20909/com.tomorrow.androidtest1 D/MainActivity: zwm, showSystemDialog
targetSdkVersion在Android 8.0及以上:
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "com.tomorrow.androidtest1"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomorrow.androidtest1">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<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">
<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>
//MainActivity
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
showSystemDialog();
}
}, 10000);
}
private void showSystemDialog() {
Log.d(TAG, "zwm, showSystemDialog");
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setTitle("Dialog")
.setMessage("Message")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); //TYPE_APPLICATION_OVERLAY
dialog.show();
}
}
//输出log
11-23 11:45:32.583 24612-24612/com.tomorrow.androidtest1 D/MainActivity: zwm, onCreate
11-23 11:45:42.843 24612-24612/com.tomorrow.androidtest1 D/MainActivity: zwm, showSystemDialog
网友评论