|
Android軟件開(kāi)發(fā)之應(yīng)用程序之間的通信介紹
Android 開(kāi)發(fā)中在程序之間通訊的接口做的還是非常豐富的 本例主要向大家介紹程序之間是如何進(jìn)行溝通,有哪幾種溝通方式 如何來(lái)實(shí)現(xiàn)溝通。
1.使用handler傳遞消息
handler 大家可以把它想象成主線程(UI線程)的一個(gè)子線程,它可以給主線程(UI線程)發(fā)送數(shù)據(jù)從而更新主線程(UI線程)的UI與邏輯,handler 是一個(gè)子線程所以它的耗時(shí)操作不會(huì)阻塞主線程,大家都知道在android的開(kāi)發(fā)中如果代碼中某個(gè)地方阻塞主線程超過(guò)5秒的話系統(tǒng)會(huì)提示ANR (系統(tǒng)提示強(qiáng)制關(guān)閉)所以在耗時(shí)操作上我們可以考慮開(kāi)啟一個(gè)子線程避免ANR。 handler會(huì)向主線程發(fā)送消息 會(huì)以隊(duì)列的形式排列著配合等待主線程更新UI 邏輯 等等。
下面這個(gè)例子詮釋了這一點(diǎn) 利用handler傳遞消息來(lái)更新主線程的UI顯示內(nèi)容 點(diǎn)擊按鈕后每過(guò)一秒通過(guò)handler發(fā)送消息更新UI線程顯示的時(shí)間 直到顯示時(shí)間更新到10 然后結(jié)束這個(gè)線程。
- public class HandlerActivity extends Activity implements Runnable{
/**更新時(shí)間**/
public final static int UPDATE_TIME =0;
/**更新時(shí)間成功**/
public final static int UPDATE_COMPLETED =1;
/**記錄顯示時(shí)間 超過(guò)10秒結(jié)束線程**/
private int mShowNumber = 0;
/**開(kāi)始計(jì)時(shí)按鈕**/
private Button mButton = null;
/**計(jì)時(shí)顯示內(nèi)容**/
private TextView mTextView = null;
/**線程**/
private Thread mThread = null;
/**線程關(guān)閉的標(biāo)志**/
private boolean mRunning = false;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle bundle= msg.getData();
//通過(guò)key的名稱拿到它的值
String number = bundle.getString("number");
//msg.what為handler接收到的消息編號(hào)
switch(msg.what) {
case UPDATE_TIME:
mTextView.setText("正在更新時(shí)間" + number);
break;
case UPDATE_COMPLETED:
mTextView.setText("更新完畢");
break;
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.handler);
/**拿到button 與 TextView 對(duì)象**/
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) {
/**點(diǎn)擊按鈕后開(kāi)始線程開(kāi)始計(jì)時(shí)**/
mRunning = true;
mThread.start();
}
});
mTextView.setText("點(diǎn)擊按鈕開(kāi)始更新時(shí)間");
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++;
/** 把須要的數(shù)據(jù)放入bandle中 **/
Bundle bandle = new Bundle();
bandle.putString("number", String.valueOf(mShowNumber));
/** 設(shè)置這條信息的編號(hào)為更新時(shí)間 **/
/** 將bandle寫(xiě)入message中 **/
/** 最后將這個(gè)message發(fā)送出去 **/
/** mShowNumber小于10更新時(shí)間 否則更新完畢 **/
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();
}
}
}
}
復(fù)制代碼 2.Notifation通知欄信息
Notifation通知欄會(huì)在屏幕上方向用戶提示信息 但是不會(huì)打斷用戶正在閱讀的內(nèi)容,除非用戶手動(dòng)將 Notifation通知欄拉下。 Notifation的好處就是在于不會(huì)影響用戶的操作,比如用戶正在閱讀非常重要的信息這時(shí)候幫他直接打開(kāi)一個(gè)activity會(huì)非常不合適 因?yàn)橹苯佑绊懙搅怂?dāng)時(shí)的操作行為 所以Notifation就出來(lái)了。建議大家在開(kāi)發(fā)中遇到可能打斷用戶使用的情況下都去使用Notifation通知欄。
屏幕上方為彈出的Notifation通知欄
將Notifation通知欄拉下后會(huì)出現(xiàn)相應(yīng)的信息
- public class NotificationActivity extends Activity {
NotificationManager mManager = null;
Notification notification =null;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.notification);
// 得到通知消息的管理器對(duì)象,負(fù)責(zé)管理 Notification 的發(fā)送與清除消息等
mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 創(chuàng)建Notification對(duì)象 參數(shù)分別代表 通知欄 中顯示的圖標(biāo) 顯示的標(biāo)題 顯示的時(shí)間
notification = new Notification(R.drawable.jay,
"Android專(zhuān)業(yè)開(kāi)發(fā)群", System.currentTimeMillis());
// 設(shè)置在通知欄中點(diǎn)擊后Notification自動(dòng)消失
notification.flags = Notification.FLAG_AUTO_CANCEL;
//設(shè)置點(diǎn)擊后轉(zhuǎn)跳的新activity
Intent intent = new Intent(this, MyShowActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_NEW_TASK);
//通過(guò)bundle可以帶一些數(shù)據(jù)過(guò)去 這里將字符串傳遞了過(guò)去
Bundle bundle = new Bundle();
bundle.putString("name", "從Notification轉(zhuǎn)跳過(guò)來(lái)的");
intent.putExtras(bundle);
//設(shè)置通知欄中顯示的內(nèi)容
PendingIntent contentIntent = PendingIntent.getActivity(this,
R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this, "Android專(zhuān)業(yè)開(kāi)發(fā)群",
"QQ群號(hào) 164257885", contentIntent);
Button button0 = (Button)findViewById(R.id.button0);
button0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//打開(kāi)這個(gè)Notification通知
mManager.notify(0, notification);
}
});
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//關(guān)閉這個(gè)Notification通知
mManager.cancelAll();
}
});
super.onCreate(savedInstanceState);
}
}
復(fù)制代碼 3.廣播的發(fā)送與接收
Android開(kāi)發(fā)中如果須要對(duì)兩個(gè)完全沒(méi)關(guān)系的程序之間進(jìn)行通信 就可以使用發(fā)送廣播與接收廣播的機(jī)制來(lái)實(shí)現(xiàn) ,例如程序A發(fā)送了一個(gè)廣播 程序B接受到 做一些事情 這樣就達(dá)到了相互的通訊。
調(diào)用sendBroadcast() 傳入intent 后 來(lái)發(fā)送廣播 - 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", "您發(fā)送了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", "您發(fā)送了Cancle這條廣播哦");
sendBroadcast(intent);
}
});
//啟動(dòng)Service
Intent i = new Intent(this, MyService.class);
startService(i);
super.onCreate(savedInstanceState);
}
}
復(fù)制代碼 接收廣播的話 我們開(kāi)啟一個(gè)service 在service中通過(guò)BroadcastReceiver 來(lái)接收廣播 前提是須要接收的廣播須要在onStart()中注冊(cè)一下 在AndroidManifest.xml中可以過(guò)濾只接收須要接收的廣播、 - <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>
復(fù)制代碼 在onStart()中注冊(cè)了程序中所需要的兩個(gè)廣播 - 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) {
//注冊(cè)這兩個(gè)廣播
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;
}
}
復(fù)制代碼 這里注意一下 service如果沒(méi)有起來(lái) 我們是接收不到廣播的 所以一定要保證接收的時(shí)候service是開(kāi)啟的,上例中的service是在打開(kāi)activity時(shí)開(kāi)啟的 但是如果用戶把手機(jī)關(guān)掉然后在開(kāi)機(jī) , 這樣的話service就不是打開(kāi)狀態(tài) 這樣就非常危險(xiǎn)了因?yàn)檫@時(shí)scrvice就接收不到任何消息了除非用戶再次進(jìn)activity 才會(huì)幫他打開(kāi)scrvice 所以我們可以在用戶開(kāi)機(jī)后就直接將scrvice打開(kāi),具體的實(shí)現(xiàn)方式如下
在AndroidManifest.xml中注冊(cè)一個(gè)開(kāi)機(jī)廣播 這個(gè)廣播系統(tǒng)只會(huì)在開(kāi)機(jī)發(fā)出而且只會(huì)發(fā)出一次 所以我們接收這個(gè)廣播就可以知道手機(jī)是否為開(kāi)機(jī)狀態(tài) - <receiver android:name=".MyBootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
復(fù)制代碼 注意加入權(quán)限 - <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
復(fù)制代碼 在BroadcastRecevier中接收開(kāi)機(jī)廣播 然后打開(kāi)service 就可以實(shí)現(xiàn)開(kāi)機(jī)啟動(dòng)service。 - public class MyBootReceiver extends BroadcastReceiver {
/**開(kāi)機(jī)廣播**/
static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
/**如果為開(kāi)機(jī)廣播則開(kāi)啟service**/
if (intent.getAction().equals(BOOT_COMPLETED)) {
Intent i = new Intent(context, MyService.class);
context.startService(i);
}
}
}
復(fù)制代碼 3.Activity與Activity之間的轉(zhuǎn)跳
在軟件應(yīng)用的開(kāi)發(fā)中肯定會(huì)有多個(gè)Activity 這樣它們之間就會(huì)存在相互轉(zhuǎn)跳的關(guān)系 轉(zhuǎn)跳的實(shí)現(xiàn)方式還是使用Intent 然后startActivity ,當(dāng)然轉(zhuǎn)跳的話是可以帶數(shù)據(jù)過(guò)去的。比如從A跳到B 可以把A中的一些數(shù)據(jù)通過(guò)Intent傳遞給B 。
讀下面這段代碼 大家會(huì)發(fā)現(xiàn)intent與bandle 傳遞數(shù)值的方式基本一樣為什么還要分成兩個(gè)呢? 確實(shí)他們兩個(gè)傳遞的數(shù)值的方式非常類(lèi)似, 他們兩個(gè)的區(qū)別就是Intent屬于把零散的數(shù)據(jù)傳遞過(guò)去 而bundle則是把零散的數(shù)據(jù)先放入bundle 然后在傳遞過(guò)去。我舉一個(gè)例子 比如我們現(xiàn)在有3個(gè)activity A.B.C 須要把A的數(shù)據(jù)穿給B然后在穿給C ,如果使用intent一個(gè)一個(gè)傳遞 須要在A類(lèi)中一個(gè)一個(gè)傳遞給B 然后B類(lèi)中獲取到所有數(shù)值 然后在一個(gè)一個(gè)傳遞給C 這樣很麻煩 但是 如果是bundle的話 B類(lèi)中直接將bundler傳遞給C 不用一個(gè)一個(gè)獲得具體的值 然后在C類(lèi)中直接取得解析數(shù)值。
傳遞 - /**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);
//把數(shù)值放進(jìn)bundle 然后在把整個(gè)bundle通過(guò)intent.putExtra()傳遞
Bundle bundle = new Bundle();
bundle.putString("b_name", "小可愛(ài)");
bundle.putInt("b_age", 23);
bundle.putBoolean("b_boy", false);
//在這里把整個(gè)bundle 放進(jìn)intent中
intent.putExtras(bundle);
//開(kāi)啟一個(gè)新的 activity 將intent傳遞過(guò)去
startActivity(intent);
}
});
復(fù)制代碼 接收 - public class ShowActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.my);
Intent intent = getIntent();
String name = intent.getStringExtra("name");
//第二個(gè)參數(shù)為默認(rèn)值 意思就是如果在intent中拿不到的話
//就用默認(rèn)值
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");
//第二個(gè)參數(shù)為默認(rèn)值 意思就是如果在bundle中拿不到的話
//就用默認(rèn)值
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);
}
}
復(fù)制代碼 最后還是那句老話如果你還是覺(jué)得我寫(xiě)的不夠詳細(xì) 看的不夠爽 不要緊我把源代碼的下載地址貼出來(lái) 歡迎大家一起討論學(xué)習(xí)
第九講 應(yīng)用程序之間的通信介紹.rar(306.01 KB, 下載次數(shù): 427)[/I]2011-9-3 00:24 上傳點(diǎn)擊文件名 下載積分: 下載豆 -2 |
上一篇: 對(duì)通訊錄的各項(xiàng)操作,完整版,經(jīng)過(guò)測(cè)試,方便后來(lái)者下一篇: Android騰訊微博客戶端開(kāi)發(fā)四:微博發(fā)送篇(QQ表情,@搜索)
|