Android中,一般情况下一个应用程序是一个独立的进程。而进程之间的内存是不可见的,那么进程间如何通信呢?
其中一种实现方式便是通过广播来实现。这种方式实现方式的特点是被动通信,因为只能发送方发送广播,接收方被动的接收广播。下面通过代码来具体讲解其具体实现方式:
1.首先写发送广播的应用程序:(这个程序的功能很简单:点击界面上的按钮发送一个Action为“android.intent.action.MY_BROADCAST”的广播)
activity_main.xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.android.monkey.testsendbroadcast.MainActivity">
<Button
android:id="@+id/btn_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击发送广播"
android:textSize="50dp"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
MainAcivity:
package com.android.monkey.testsendbroadcast;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
findViewById(R.id.btn_click).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent =
new Intent("android.intent.action.MY_BROADCAST");
intent.putExtra("data","This is a broadcast!");
sendBroadcast(intent);
Toast.makeText(MainActivity.this,"已经发送了广播",Toast.LENGTH_LONG).show();
}
}
);
}
}
2.写接收广播的应用程序:
activity_main.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.android.monkey.testreceivebroadcast.MainActivity">
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="显示接收到的广播"
android:textSize="30dp" />
</RelativeLayout>
自定义的广播接收器MyReceiver:
package com.android.monkey.testreceivebroadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
private MainActivity.Callback callback;
public void setCallback(MainActivity.Callback callback) {
this.callback = callback;//接收到广播之后的回调
}
@Override
public void onReceive(Context context, Intent intent) {
if(intent!=null){
String action = intent.getAction();
Log.e(MainActivity.TAG, "接收到的广播 action: "+action);
if(action!=null && action.equals(MainActivity.ACTION_MY_BROADCAST)){
String text = intent.getStringExtra("data");
if(callback!=null){
callback.updateUi(text);
}
}
}
}
}
MainAcivity:
package com.android.monkey.testreceivebroadcast;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public final static String TAG = "receiver";
public final static String ACTION_MY_BROADCAST = "android.intent.action.MY_BROADCAST";
private TextView mTvText;
private MyReceiver mMyReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "MainActivity onCreate 执行...");
setContentView(R.layout.activity_main);
initView();
//registReceiver();
}
private void registReceiver() {
mMyReceiver = new MyReceiver();
mMyReceiver.setCallback(new Callback() {
@Override
public void updateUi(String text) {
if(mTvText!=null&& !TextUtils.isEmpty(text)){
mTvText.setText(text);
}
}
});
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_MY_BROADCAST);
registerReceiver(mMyReceiver,filter);
}
private void initView() {
mTvText = (TextView)findViewById(R.id.tv_text);
}
@Override
protected void onDestroy() {
super.onDestroy();
//unregisterReceiver();
}
private void unregisterReceiver() {
unregisterReceiver(mMyReceiver);
}
public interface Callback{
void updateUi(String text);
}
}
同时为了方便看清广播静态注册和动态注册的区别,我们写了自定义的Application(主要是打印一条log信息):
package com.android.monkey.testreceivebroadcast;
import android.app.Application;
import android.util.Log;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Log.e(MainActivity.TAG, "MyApplication onCreate执行...");
}
}
Manifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.monkey.testreceivebroadcast">
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_BROADCAST"/>
</intent-filter>
</receiver>-->
</application>
</manifest>
动态注册广播:分别取消对MainActivity的onCreate()和onDestroy()中注册和取消注册广播代码的注释。同时将manifest.xml文件中静态注册广播的代码注释掉。然后执行以下操作:
第一种情况:
1.运行接收广播的应用程序
打印log:
01-05 02:13:24.165 3794-3794/com.android.monkey.testreceivebroadcast E/receiver: MyApplication onCreate执行…
01-05 02:13:24.247 3794-3794/com.android.monkey.testreceivebroadcast E/receiver: MainActivity onCreate 执行…
2.按Back键退出接收广播的应用程序,并杀掉该应用程序的进程;(此时该应用程序的MainActivity已经被销毁了,广播注销注册);
3.运行发送广播的应用程序,并点击按钮发送广播。此时控制台并没有打印出接收到广播的log。这是显而易见的,因为接收广播的应用程序已经被销毁了。同时界面无任何反应。
第二种情况:
1.运行接收广播的应用程序
打印log:
01-05 02:39:24.998 25156-25156/? E/receiver: MyApplication onCreate执行…
01-05 02:39:25.384 25156-25156/com.android.monkey.testreceivebroadcast E/receiver: MainActivity onCreate 执行…
2.按Home键退出接收广播的应用程序(此时该应用程序的MainActivity并没有被销毁了,广播没有注销注册);
3.运行发送广播的应用程序,并点击按钮发送广播。
此时控制台打印出接收到广播的log:
01-05 02:41:10.841 26494-26494/com.android.monkey.testreceivebroadcast E/receiver: 接收到的广播 action: android.intent.action.MY_BROADCAST 同时界面显示出“This is a broadcast!”
静态注册广播:对MainActivity的onCreate()和onDestroy()中注册和取消注册广播代码的注释调。同时取消对manifest.xml文件中静态注册广播代码的注释。然后执行以下操作:
第一种情况:
1.运行接收广播的应用程序
打印log:
01-05 02:50:16.895 9362-9362/com.android.monkey.testreceivebroadcast E/receiver: MyApplication onCreate执行…
01-05 02:50:16.983 9362-9362/com.android.monkey.testreceivebroadcast E/receiver: MainActivity onCreate 执行…
2.按Back键退出接收广播的应用程序,并杀掉该应用程序的进程;
3.运行发送广播的应用程序,并点击按钮发送广播。
此时控制台打印出接收到广播的log:
01-05 02:53:16.783 14791-14791/? E/receiver: MyApplication onCreate执行…
01-05 02:53:16.784 14791-14791/? E/receiver: 接收到的广播 action: android.intent.action.MY_BROADCAST MyReceiver中的CallBack为空。后台Activity栈中没有发送广播应用程序的Activity,所以看不到界面显示。
第二种情况:
1.运行接收广播的应用程序
打印log:
01-05 02:55:40.026 17578-17578/com.android.monkey.testreceivebroadcast E/receiver: MyApplication onCreate执行…
01-05 02:55:40.377 17578-17578/com.android.monkey.testreceivebroadcast E/receiver: MainActivity onCreate 执行…
2.按Home键退出接收广播的应用程序(此时该应用程序的MainActivity并没有被销毁了,广播没有注销注册);
3.运行发送广播的应用程序,并点击按钮发送广播。
此时控制台打印出接收到广播的log:
01-05 02:56:07.507 17578-17578/com.android.monkey.testreceivebroadcast E/receiver: 接收到的广播 action: android.intent.action.MY_BROADCAST 这里虽然接收到了广播,但是callback为空所以界面没有显示。
总结:
动态注册广播时只有在注册广播之后取消注册之前的有效期内才能接收到广播。
静态注册广播时就算应用没有启动也能接收到广播,会执行Application的OnCreate(),但不会执行Actvity的onCreate()。