Android軟體開發之應用程式之間的通訊介紹
雨松MOMO原創文章如轉載,請註明:轉載至我的獨立網域名稱部落格雨松MOMO程式研究院,原文地址:http://www.xuanyusong.com/archives/141
Android 開發中在程式之間通訊的介面做的還是非常豐富的 本例主要向大家介紹程式之間是如何進行溝通,有哪幾種溝通方式 如何來實現溝通。
1.使用handler傳遞訊息
handler 大家可以把它想象成主線程(UI線程)的一個子線程,它可以給主線程(UI線程)發送資料從而更新主線程(UI線程)的UI與邏輯,handler 是一個子線程所以它的耗時操作不會阻塞主線程,大家都知道在android的開發中如果代碼中某個地方阻塞主線程超過5秒的話系統會提示ANR (系統提示強制關閉)所以在耗時操作上我們可以考慮開啟一個子線程避免ANR。 handler會向主線程發送訊息 會以隊列的形式排列著配合等待主線程更新UI 邏輯 等等。
下面這個例子詮釋了這一點 利用handler傳遞訊息來更新主線程的UI顯示內容 點擊按鈕後每過一秒通過handler發送訊息更新UI線程顯示的時間 直到顯示時間更新到10 然後結束這個線程。
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() {@Overridepublic 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通知欄拉下後會出現相應的資訊
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;//設定點擊後轉跳的新activityIntent 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 後 來發送廣播
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中可以過濾只接收須要接收的廣播、
<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()中註冊了程式中所需要的兩個廣播
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() {@Overridepublic 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中註冊一個開機廣播 這個廣播系統只會在開機發出而且只會發出一次 所以我們接收這個廣播就可以知道手機是否為開機狀態
<receiver android:name=".MyBootReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
注意加入許可權
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
在BroadcastRecevier中接收開機廣播 然後開啟service 就可以實現開機啟動service。
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類中直接取得解析數值。
傳遞
/**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); }});
接收
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); }}
最後還是那句老話如果你還是覺得我寫的不夠詳細 看的不夠爽 不要緊我把原始碼的貼出來 歡迎大家一起討論學習雨松MOMO希望可以和大家一起進步。
:http://www.xuanyusong.com/archives/141