美文网首页
新特性与行为变更 -- 代码2

新特性与行为变更 -- 代码2

作者: TomyZhang | 来源:发表于2019-11-23 17:07 被阅读0次

运行时权限

运行时权限

在应用间共享文件

FileProvider

计划排定作业

JobIntentService(android.support.v4.app.JobIntentService)

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

相关文章

网友评论

      本文标题:新特性与行为变更 -- 代码2

      本文链接:https://www.haomeiwen.com/subject/tnbhwctx.html