Android 開發中在程序之間通訊的接口做的還是非常豐富的 本例主要向大家介紹程序之間是如何進行溝通,有哪幾種溝通方式 如何來實現溝通。
1.使用handler傳遞消息
handler 大家可以把它想象成主線程(UI線程)的一個子線程,它可以給主線程(UI線程)發送數據從而更新主線程(UI線程)的UI與邏輯,handler 是一個子線程所以它的耗時操作不會阻塞主線程,大家都知道在android的開發中如果代碼中某個地方阻塞主線程超過5秒的話系統會提示ANR (系統提示強制關閉)所以在耗時操作上我們可以考慮開啟一個子線程避免ANR。 handler會向主線程發送消息 會以隊列的形式排列著配合等待主線程更新UI 邏輯 等等。
下面這個例子诠釋了這一點 利用handler傳遞消息來更新主線程的UI顯示內容 點擊按鈕後每過一秒通過handler發送消息更新UI線程顯示的時間 直到顯示時間更新到10 然後結束這個線程。
Java代碼
- public class HandlerActivity extends Activity implements Runnable{
-
- /**更新時間**/
- public final static int UPDATE_TIME =0;
- /**更新時間成功**/
- public final static int UPDATE_COMPLETED =1;
-
- /**記錄顯示時間 超過10秒結束線程**/
- private int mShowNumber = 0;
-
- /**開始計時按鈕**/
- private Button mButton = null;
-
- /**計時顯示內容**/
- private TextView mTextView = null;
-
- /**線程**/
- private Thread mThread = null;
-
- /**線程關閉的標志**/
- private boolean mRunning = false;
-
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
-
- Bundle bundle= msg.getData();
- //通過key的名稱拿到它的值
- String number = bundle.getString("number");
- //msg.what為handler接收到的消息編號
- switch(msg.what) {
- case UPDATE_TIME:
- mTextView.setText("正在更新時間" + number);
- break;
- case UPDATE_COMPLETED:
- mTextView.setText("更新完畢");
- break;
- }
- super.handleMessage(msg);
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setContentView(R.layout.handler);
-
- /**拿到button 與 TextView 對象**/
- mButton = (Button)findViewById(R.id.button0);
- mTextView = (TextView)findViewById(R.id.textView0);
- mThread = new Thread(this);
-
- mButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- /**點擊按鈕後開始線程開始計時**/
- mRunning = true;
- mThread.start();
- }
- });
-
- mTextView.setText("點擊按鈕開始更新時間");
- super.onCreate(savedInstanceState);
- }
-
- public void ShowDialog(String string) {
- AlertDialog.Builder builder = new AlertDialog.Builder(
- HandlerActivity.this);
- builder.setIcon(R.drawable.icon);
- builder.setTitle(string);
- builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- finish();
- }
- });
- builder.show();
- }
-
- @Override
- public void run() {
-
- while (mRunning) {
- try {
- mShowNumber++;
- /** 把須要的數據放入bandle中 **/
- Bundle bandle = new Bundle();
- bandle.putString("number", String.valueOf(mShowNumber));
-
- /** 設置這條信息的編號為更新時間 **/
- /** 將bandle寫入message中 **/
- /** 最後將這個message發送出去 **/
- /** mShowNumber小於10更新時間 否則更新完畢 **/
- Message msg = new Message();
- if(mShowNumber <=10) {
- msg.what = UPDATE_TIME;
- }else {
- mRunning = false;
- msg.what = UPDATE_COMPLETED;
- }
- msg.setData(bandle);
- handler.sendMessage(msg);
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
2.Notifation通知欄信息
Notifation通知欄會在屏幕上方向用戶提示信息 但是不會打斷用戶正在閱讀的內容,除非用戶手動將 Notifation通知欄拉下。 Notifation的好處就是在於不會影響用戶的操作,比如用戶正在閱讀非常重要的信息這時候幫他直接打開一個activity會非常不合適 因為直接影響到了他當時的操作行為 所以Notifation就出來了。建議大家在開發中遇到可能打斷用戶使用的情況下都去使用Notifation通知欄。
屏幕上方為彈出的Notifation通知欄
將Notifation通知欄拉下後會出現相應的信息
Java代碼
- public class NotificationActivity extends Activity {
- NotificationManager mManager = null;
- Notification notification =null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setContentView(R.layout.notification);
-
- // 得到通知消息的管理器對象,負責管理 Notification 的發送與清除消息等
- mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- // 創建Notification對象 參數分別代表 通知欄 中顯示的圖標 顯示的標題 顯示的時間
- notification = new Notification(R.drawable.jay,
- "Android專業開發群", System.currentTimeMillis());
-
- // 設置在通知欄中點擊後Notification自動消失
- notification.flags = Notification.FLAG_AUTO_CANCEL;
-
- //設置點擊後轉跳的新activity
- Intent intent = new Intent(this, MyShowActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP¦ Intent.FLAG_ACTIVITY_NEW_TASK);
-
- //通過bundle可以帶一些數據過去 這裡將字符串傳遞了過去
- Bundle bundle = new Bundle();
- bundle.putString("name", "從Notification轉跳過來的");
- intent.putExtras(bundle);
-
- //設置通知欄中顯示的內容
- PendingIntent contentIntent = PendingIntent.getActivity(this,
- R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);
- notification.setLatestEventInfo(this, "Android專業開發群",
- "QQ群號 164257885", contentIntent);
-
- Button button0 = (Button)findViewById(R.id.button0);
- button0.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- //打開這個Notification通知
- mManager.notify(0, notification);
- }
- });
-
- Button button1 = (Button)findViewById(R.id.button1);
- button1.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- //關閉這個Notification通知
- mManager.cancelAll();
- }
- });
-
- super.onCreate(savedInstanceState);
- }
-
- }
3.廣播的發送與接收
Android開發中如果須要對兩個完全沒關系的程序之間進行通信 就可以使用發送廣播與接收廣播的機制來實現 ,例如程序A發送了一個廣播 程序B接受到 做一些事情 這樣就達到了相互的通訊。
調用sendBroadcast() 傳入intent 後 來發送廣播
Java代碼
- public class BroadcastActivity extends Activity {
-
- Button mButton0 = null;
- Button mButton1 = null;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setContentView(R.layout.broadcast);
-
- mButton0 = (Button)findViewById(R.id.button0);
- mButton0.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- Intent intent = new Intent(MyService.SEND_OK_MESSAGE);
- intent.putExtra("name", "您發送了OK這條廣播哦");
- sendBroadcast(intent);
- }
- });
-
- mButton1 = (Button)findViewById(R.id.button1);
- mButton1.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- Intent intent = new Intent(MyService.SEND_CANCLE_MESSAGE);
- intent.putExtra("name", "您發送了Cancle這條廣播哦");
- sendBroadcast(intent);
- }
- });
-
- //啟動Service
- Intent i = new Intent(this, MyService.class);
- startService(i);
- super.onCreate(savedInstanceState);
- }
- }
接收廣播的話 我們開啟一個service 在service中通過BroadcastReceiver 來接收廣播 前提是須要接收的廣播須要在onStart()中注冊一下 在AndroidManifest.xml中可以過濾只接收須要接收的廣播。
XML/HTML代碼
- <service android:name=".MyService">
- <intent-filter>
- <action android:name="cn.m15.xys.MyService"></action>
- </intent-filter>
- <intent-filter>
- <action android:name="send.ok.message" />
- <action android:name="send.cancle.message" />
- </intent-filter>
- </service>
在onStart()中注冊了程序中所需要的兩個廣播
Java代碼
- public class MyService extends Service {
-
- public final static String SEND_OK_MESSAGE = "send.ok.message";
- public final static String SEND_CANCLE_MESSAGE = "send.cancle.message";
-
- private BroadcastReceiver myBroadCast = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(SEND_OK_MESSAGE)) {
- Toast.makeText(context, "接收到了一條廣播為" + SEND_OK_MESSAGE, Toast.LENGTH_LONG).show();
- }else if(action.equals(SEND_CANCLE_MESSAGE)) {
- Toast.makeText(context, "接收到了一條廣播為" + SEND_CANCLE_MESSAGE, Toast.LENGTH_LONG).show();
- }
- }
-
- };
-
- @Override
- public void onCreate() {
- super.onCreate();
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
- //注冊這兩個廣播
- IntentFilter myFilter = new IntentFilter();
- myFilter.addAction(SEND_OK_MESSAGE);
- myFilter.addAction(SEND_CANCLE_MESSAGE);
- this.registerReceiver(myBroadCast, myFilter);
- super.onStart(intent, startId);
- }
- @Override
- public IBinder onBind(Intent arg0) {
- return null;
- }
-
- }
這裡注意一下 service如果沒有起來 我們是接收不到廣播的 所以一定要保證接收的時候service是開啟的,上例中的service是在打開activity時開啟的 但是如果用戶把手機關掉然後在開機 , 這樣的話service就不是打開狀態 這樣就非常危險了因為這時scrvice就接收不到任何消息了除非用戶再次進activity 才會幫他打開scrvice 所以我們可以在用戶開機後就直接將scrvice打開,具體的實現方式如下
在AndroidManifest.xml中注冊一個開機廣播 這個廣播系統只會在開機發出而且只會發出一次 所以我們接收這個廣播就可以知道手機是否為開機狀態
XML/HTML代碼
- <receiver android:name=".MyBootReceiver" >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- </intent-filter>
- </receiver>
注意加入權限
XML/HTML代碼
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
在BroadcastRecevier中接收開機廣播 然後打開service 就可以實現開機啟動service。
Java代碼
- public class MyBootReceiver extends BroadcastReceiver {
- /**開機廣播**/
- static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- /**如果為開機廣播則開啟service**/
- if (intent.getAction().equals(BOOT_COMPLETED)) {
- Intent i = new Intent(context, MyService.class);
- context.startService(i);
- }
-
- }
- }
3.Activity與Activity之間的轉跳
在軟件應用的開發中肯定會有多個Activity 這樣它們之間就會存在相互轉跳的關系 轉跳的實現方式還是使用Intent 然後startActivity ,當然轉跳的話是可以帶數據過去的。比如從A跳到B 可以把A中的一些數據通過Intent傳遞給B 。
讀下面這段代碼 大家會發現intent與bandle 傳遞數值的方式基本一樣為什麼還要分成兩個呢? 確實他們兩個傳遞的數值的方式非常類似, 他們兩個的區別就是Intent屬於把零散的數據傳遞過去 而bundle則是把零散的數據先放入bundle 然後在傳遞過去。我舉一個例子 比如我們現在有3個activity A.B.C 須要把A的數據穿給B然後在穿給C ,如果使用intent一個一個傳遞 須要在A類中一個一個傳遞給B 然後B類中獲取到所有數值 然後在一個一個傳遞給C 這樣很麻煩 但是 如果是bundle的話 B類中直接將bundler傳遞給C 不用一個一個獲得具體的值 然後在C類中直接取得解析數值。
傳遞
Java代碼
- /**Activity之間傳遞值**/
- Button botton3 = (Button)findViewById(R.id.button3);
- botton3.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- Intent intent = new Intent(mContext,ShowActivity.class);
- //使用intent.putExtra()直接傳遞
- intent.putExtra("name", "雨松MOMO");
- intent.putExtra("age", 25);
- intent.putExtra("boy", true);
-
- //把數值放進bundle 然後在把整個bundle通過intent.putExtra()傳遞
- Bundle bundle = new Bundle();
- bundle.putString("b_name", "小可愛");
- bundle.putInt("b_age", 23);
- bundle.putBoolean("b_boy", false);
- //在這裡把整個bundle 放進intent中
- intent.putExtras(bundle);
- //開啟一個新的 activity 將intent傳遞過去
- startActivity(intent);
- }
- });
接收
Java代碼
- public class ShowActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setContentView(R.layout.my);
-
- Intent intent = getIntent();
-
- String name = intent.getStringExtra("name");
- //第二個參數為默認值 意思就是如果在intent中拿不到的話
- //就用默認值
- int age = intent.getIntExtra("age", 0);
- boolean isboy = intent.getBooleanExtra("boy", false);
- TextView textView0 = (TextView)findViewById(R.id.text0);
-
- textView0.setText("姓名 " + name + "年齡 " + age + "男孩? " + isboy);
-
- Bundle bundle = intent.getExtras();
- name = bundle.getString("b_name");
- //第二個參數為默認值 意思就是如果在bundle中拿不到的話
- //就用默認值
- age = bundle.getInt("b_age",0);
- isboy = bundle.getBoolean("b_boy", false);
-
- TextView textView1 = (TextView)findViewById(R.id.text1);
-
- textView1.setText("姓名 " + name + "年齡 " + age + "男孩? " + isboy);
-
- super.onCreate(savedInstanceState);
- }
-
- }
源碼下載地址:http://vdisk.weibo.com/s/aa3fI