1.基于消息的通信機(jī)制 Intent ---boudle ,extra
數(shù)據(jù)類型有限,比如遇到不可序列化的數(shù)據(jù)Bitmap,InputStream, 或者LinkList鏈表等等數(shù)據(jù)類型就不太好用。
2. 利用static靜態(tài)數(shù)據(jù), public static成員變量;
3.基于外部存儲(chǔ)的傳輸, File/Preference/ Sqlite ,如果要針對(duì)第三方應(yīng)用需要Content Provider
4.基于IPC的通信機(jī)制
context 與Service之間的傳輸,如Activity與Service之間的通信,定義AIDL接口文件。
示例: http://www./thread-36249-1-1.html
5. 基于Application Context, 例子如下文:
在當(dāng)前Activity將兩個(gè)值傳到了Test中。但如果遇到不可序列化的數(shù)據(jù),如Bitmap、InputStream等,intent就無(wú)能為力了。因此,我們很自然地會(huì)想到另外一種方法,靜態(tài)變量。如下面的代碼所示:
public class Product extends Activity
{
public static Bitmap mBitmap;
}
對(duì)于上面的代碼來(lái)說(shuō),其他任何類可以直接使用Product中的mBitmap變量。這么做很easy、也很cool,但卻very very wrong。我們千萬(wàn)不要以為Davlik虛擬機(jī)的垃圾回收器會(huì)幫助我們回收不需要的內(nèi)存垃圾。事實(shí)上,回收器并不可靠,尤其是手機(jī)上,是更加的不可靠。 因此,除非我們要使自己的程序變得越來(lái)越糟糕,否則盡量遠(yuǎn)離static。
注:如果經(jīng)常使用static的Bitmap、Drawable等變量。可能就會(huì)拋出一個(gè)在Android系統(tǒng)中非常著名的異常(以前budget這個(gè)單詞一直記不住什么意思,自從經(jīng)常拋出這個(gè)異常后,這個(gè)單詞終于爛熟于心了, )
ERROR/AndroidRuntime(4958): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
如果不使用static,總得有方法來(lái)代替它(盡管我很喜歡public static,我相信很多人也喜歡它,但為了我們的程序,建議還是忍痛割愛(ài)吧),那么這個(gè)新的解決方案就是本文的主題,這就是Application Context,相當(dāng)于Web程序的Application,它的生命周期和應(yīng)用程序一樣長(zhǎng)(這個(gè)我喜歡)。
那么現(xiàn)在來(lái)看看如何使用這個(gè)Application Context。我們可以通過(guò)Context.getApplicationContext或Context.getApplication方法獲得 Application Context。但要注意,我們獲得的只是Context對(duì)象,而更理想的方法是獲得一個(gè)類的對(duì)象。ok,說(shuō)干就干,下面來(lái)定義一個(gè)類。
package net.blogjava.mobile1;
import android.app.Application;
import android.graphics.Bitmap;
public class MyApp extends Application
{
private Bitmap mBitmap;
public Bitmap getBitmap()
{
return mBitmap;
}
public void setBitmap(Bitmap bitmap)
{
this .mBitmap = bitmap;
}
}
上面這個(gè)類和普通的類沒(méi)什么本質(zhì)的不同。但該類是Application的子類。對(duì)了,這就是使用Application Context的第一步,定義一個(gè)繼承自Application的類。然后呢,就在這個(gè)類中定義任何我們想使其全局存在的變量了,如本例中的 Bitmap。下面還需要一個(gè)重要的步驟,就是在<application>標(biāo)簽中使用android:name屬性來(lái)指定這個(gè)類,代碼如 下:
< application android:name =".MyApp" android:icon ="@drawable/icon" android:label ="@string/app_name" >
</ application?
接下來(lái)的最后一步就是向MyApp對(duì)象中存入Bitmap對(duì)象,或從MyApp對(duì)象中取出Bitmap對(duì)象了,存入Bitmap對(duì)象的代碼如下:
MyApp myApp = (MyApp)getApplication();
Bitmap bitmap = BitmapFactory.decodeResource( this .getResources(), R.drawable.icon);
myApp.setBitmap(bitmap);
獲得Bitmap對(duì)象的代碼:
ImageView imageview = (ImageView)findViewById(R.id.ivImageView);
MyApp myApp = (MyApp)getApplication();
imageview.setImageBitmap(myApp.getBitmap());
上面兩段代碼可以在任何的Service、Activity中使用。全局的。
參考:
1.http:///?p=229
2.http://blog.csdn.net/nokiaguy/archive/2010/11/10/5998986.aspx
轉(zhuǎn)載自:http://blog.csdn.net/kieven2008/archive/2010/11/13/6006905.aspx
一、基于消息的通信機(jī)制 Intent ---boudle ,extra
Android為了屏蔽進(jìn)程的概念,利用不同的組件[Activity、Service]來(lái)表示進(jìn)程之間的通信!
組件間通信的核心機(jī)制是Intent,通過(guò)Intent可以開(kāi)啟一個(gè)Activity或Service,不論這個(gè)Activity或Service是屬于當(dāng)前應(yīng)用還是其它應(yīng)用的!
Intent包含兩部分:
1、目的[action]--要往哪里去
2、內(nèi)容[category、data]--路上帶了些啥,區(qū)分性數(shù)據(jù)或內(nèi)容性數(shù)據(jù)
Intent類型:
1、顯式--直接指定消息目的地,只適合同一進(jìn)程內(nèi)的不同組件之間通信
new Intent(this,Target.class)
2、隱式--AndroidMainifest.xml中注冊(cè),一般用于跨進(jìn)程通信
new Intent(String action)
實(shí)現(xiàn)-Intent簡(jiǎn)單進(jìn)程間通信
顯式的Intent較為簡(jiǎn)單!
如何實(shí)現(xiàn)隱式Intent呢?
在AndroidManifest.xml文件中定義<activity>
說(shuō)明:
1、一個(gè)<activity>包括:
零個(gè)或多個(gè)<intent-filter>
它主要是作為匹配的標(biāo)準(zhǔn),能否匹配成功由<action>、<category>、<data>三個(gè)tag共同決定的。
2、一個(gè)<intent-filter>包括:
一個(gè)或多個(gè) <action>
零個(gè)或多個(gè) <category>
指定<activity>的分類特征
eg:
<category android:name="android.intent.category.LAUNCHER" />
--說(shuō)明該<activity>是該project運(yùn)行的第一個(gè)界面
<category android:name="android.intent.category.HOME" />
--說(shuō)明該<activity>可以作為L(zhǎng)auncher的,即系統(tǒng)操作界面
<category android:name="android.intent.category.DEFAULT" />
--缺省情況
零個(gè)或一個(gè) <data>
-- 指定攜帶的數(shù)據(jù)的類型,使用MIME類型描述方式來(lái)描述
eg:
<data android:mimeType="video/mpeg" />
video/mpeg表示編碼格式為mpeg的視頻,
也可以使用通配符video/*表示任意格式的視頻文件類型;
在查詢ContentProvider時(shí),可以使用
<data android:mimeType="vnd.android.cursor.dir/vnd.myq.note" />
查詢上來(lái)的數(shù)據(jù)是多個(gè)記錄
<data android:mimeType="vnd.android.cursor.item/vnd.myq.note" />
查詢上來(lái)的數(shù)據(jù)是單個(gè)記錄
如上設(shè)置,要重寫(xiě)SQLiteOpenHelper的getType(Uri uri)方法
eg:
@Override
public String getType(Uri uri) {
final int match = sUriMatcher.match(uri) ;
switch(match)
{
case NOTES :
case LIVE_FOLDER_NOTES:
return "vnd.android.cursor.dir/vnd.myq.note" ;
case NOTES_ID :
return "vnd.android.cursor.item/vnd.myq.note" ;
default:
throw new IllegalArgumentException("invalid uri : " + uri) ;
}
}
數(shù)據(jù)的URI由scheme(協(xié)議),host,port,path四部分:scheme://host:port/path
<data android:scheme="http://localhost:8080/test.jsp" />
3、一個(gè)Intent對(duì)應(yīng)多種匹配結(jié)果的處理說(shuō)明
一個(gè)intent有多個(gè)可匹配的處理組件,系統(tǒng)如何處理?
分響應(yīng)消息的組件類型:
1)如果是service那么這些service都可以啟動(dòng)并處理消息。
2)如果是Activity則會(huì)彈出一個(gè)對(duì)話框讓用戶進(jìn)行選擇。
4、安全性問(wèn)題
如果不同進(jìn)程間的組件可以通過(guò)隱式消息互相通信,那程序不是可以輕易調(diào)用到其他的程序或者系統(tǒng)中的一些敏感程序的組件,這樣會(huì)不會(huì)很不安全呢?
其實(shí)Android在安全方面有一個(gè)統(tǒng)一,完備和輕便的安全策略模型。
簡(jiǎn)單一點(diǎn)說(shuō)就是:權(quán)限設(shè)置問(wèn)題
我們可以自己定義permission,然后在需要的組件處設(shè)置該permission,那么用戶要想該組件,必須要配置該permission,否則訪問(wèn)失敗的!
eg:
1、定義permission
<permission-group android:name="android.permission-group.MYQ_INFO"/>
<permission
android:name="com.myq.android.permission.DATETIME_SERVICE"
android:permissionGroup="android.permission-group.MYQ_INFO"
android:protectionLevel="normal"
/>
2、配置permission
<service android:name=".DateTimeService" android:permission="com.myq.android.permission.DATETIME_SERVICE">
<intent-filter>
<action android:name="com.myq.android.MultiProcessTest.DATETIMESERVICE_ACTION" />
</intent-filter>
</service>
3、使用permission
<uses-permission android:name="com.myq.android.permission.DATETIME_SERVICE"/>
二.基于IPC的通信機(jī)制
有了Intent這種基于消息的進(jìn)程內(nèi)或進(jìn)程間通信模型,我們就可以通過(guò)Intent去開(kāi)啟一個(gè)Service,可以通過(guò)Intent跳轉(zhuǎn)到另一個(gè)Activity,不論上面的Service或Activity是在當(dāng)前進(jìn)程還是其它進(jìn)程內(nèi)即不論是當(dāng)前應(yīng)用還是其它應(yīng)用的Service或Activity,通過(guò)消息機(jī)制都可以進(jìn)行通信!
但是通過(guò)消息機(jī)制實(shí)現(xiàn)的進(jìn)程間通信,有一個(gè)弊端就是,如果我們的Activity與Service之間的交往不是簡(jiǎn)單的Activity開(kāi)啟Service操作,而是要隨時(shí)發(fā)一些控制請(qǐng)求,那么必須就要保證Activity在Service的運(yùn)行過(guò)程中隨時(shí)可以連接到Service。
eg:音樂(lè)播放程序
后臺(tái)的播放服務(wù)往往獨(dú)立運(yùn)行,以方便在使用其他程序界面時(shí)也能聽(tīng)到音樂(lè)。同時(shí)這個(gè)后臺(tái)播放服務(wù)也會(huì)定義一個(gè)控制接口,比如播放,暫停,快進(jìn)等方法,任何時(shí)候播放程序的界面都可以連接到播放服務(wù),然后通過(guò)這組控制接口方法對(duì)其控制。
如上的需求僅僅通過(guò)Intent去開(kāi)啟Service就無(wú)法滿足了!從而Android的顯得稍微笨重的IPC機(jī)制就出現(xiàn)了,然而它的出現(xiàn)只適用于Activity與Service之間的通信,類似于遠(yuǎn)程方法調(diào)用,就像是C/S模式的訪問(wèn),通過(guò)定義AIDL接口文件來(lái)定義一個(gè)IPC接口,Server端實(shí)現(xiàn)IPC接口,Client端調(diào)用IPC接口的本地代理。
由于IPC調(diào)用是同步的,如果一個(gè)IPC服務(wù)需要超過(guò)幾毫秒的時(shí)間才能完成的話,你應(yīng)該避免在Activity的主線程中調(diào)用,否則IPC調(diào)用會(huì)掛起應(yīng)用程序?qū)е陆缑媸ロ憫?yīng)。在 這種情況下,應(yīng)該考慮單起一個(gè)線程來(lái)處理IPC訪問(wèn)。
兩個(gè)進(jìn)程間IPC看起來(lái)就象是一個(gè)進(jìn)程進(jìn)入另一個(gè)進(jìn)程執(zhí)行代碼然后帶著執(zhí)行的結(jié)果返回。
IPC機(jī)制鼓勵(lì)我們“盡量利用已有功能,利用IPC和包含已有功能的程序協(xié)作完成一個(gè)完整的項(xiàng)目”
IPC實(shí)現(xiàn)demo:
我的
project -- MultiProcessTest
package -- com.myq.android.MultiProcessTest
1、AIDL文件,我是放在package下,
文件名稱為:
IDateTimeService.aidl
文件內(nèi)容為:
package com.myq.android.MultiProcessTest ;
interface IDateTimeService
{
String getCurrentDateTime(in String format) ;
}
如果正確配置,會(huì)在gen下,生成同名的java文件
簡(jiǎn)單摘要:
//我們需要實(shí)現(xiàn)的類Stub
public interface IDateTimeService extends android.os.IInterface
{
...
public static abstract class Stub
extends android.os.Binder
implements com.myq.android.MultiProcessTest.IDateTimeService
{
...
//獲取實(shí)例的方法asInterface
public static com.myq.android.MultiProcessTest.IDateTimeService asInterface(android.os.IBinder obj)
{
...
}
...
}
//我們自己的業(yè)務(wù)方法,需要實(shí)現(xiàn)的
public java.lang.String getCurrentDateTime(java.lang.String format) throws android.os.RemoteException;
}
2、Service中實(shí)現(xiàn)IDateTimeService.Stub
eg:
package com.myq.android.MultiProcessTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class DateTimeService extends Service {
public static final String DATETIME_SERVICE_ACTION = "com.myq.android.MultiProcessTest.DATETIMESERVICE_ACTION" ;
private static final String TAG = "--------DateTimeService-------" ;
private SimpleDateFormat sdf ;
private final IDateTimeService.Stub stub = new IDateTimeService.Stub()
{
public String getCurrentDateTime(String format) throws RemoteException {
return getCurrentDateTimeString(format) ;
}
} ;
private synchronized String getCurrentDateTimeString(String format)
{
sdf = new SimpleDateFormat(format) ;
final String temp = sdf.format(new Date()) ;
Log.i(TAG,"getCurrentDateTimeString--" + Thread.currentThread() + "--" + temp) ;
return temp ;
}
public IBinder onBind(Intent arg0)
{
Log.i(TAG, "onBind--" + Thread.currentThread()) ;
return stub;
}
}
3、Client端代碼實(shí)現(xiàn)
private ServiceConnection mServiceConn = new ServiceConnection()
{
public void onServiceConnected(ComponentName name, IBinder service) {
mDateTimeService = IDateTimeService.Stub.asInterface(service) ;
}
public void onServiceDisconnected(ComponentName name) {
mDateTimeService = null ;
}
} ;
說(shuō)明:
網(wǎng)上的好多資料都沒(méi)有涉及IPC調(diào)用的AIDL的具體說(shuō)明!
它本質(zhì)上是Server端和Client端都具有相同的AIDL文件,要位于相同的包下,即package的包名藥一樣,然后才能正確的通過(guò)proxy訪問(wèn),否則client與server的aidl文件處于不同package會(huì)出錯(cuò)的。
aidl模型如下:
|<--------------------aidl---------------------->|
client端-->proxy ----------parcel數(shù)據(jù)包-------- stub<---server端
從而proxy+parcel+stub構(gòu)成了aidl.
只不過(guò),proxy運(yùn)行在客戶進(jìn)程,而stub運(yùn)行在服務(wù)端進(jìn)程。
當(dāng)你通過(guò)aidl去訪問(wèn)服務(wù)端時(shí),客戶端會(huì)阻塞在proxy,服務(wù)端處理完后,通知proxy返回。
四、附件及說(shuō)明
1、
附件是我測(cè)試所用的demo,我用的系統(tǒng)是ubuntu9,Android2.2版本
基本功能:
可以根據(jù)用戶選擇的不同輸出格式輸出當(dāng)前系統(tǒng)的時(shí)間。
2、
運(yùn)行順序:
先運(yùn)行Server端:MultiProcessTest
再運(yùn)行Client端:MultiProcessTestClient
3、
注意點(diǎn):
Server和Client端的AIDL文件必須要位于同package下,否則會(huì)出錯(cuò)
安全性問(wèn)題實(shí)現(xiàn),權(quán)限控制--定義、配置、使用
異步處理問(wèn)題--Handler