澳门新莆京赌场网站app[转]Android中先后和Service交互的点子——交互方式

郑州住宅公积金

正文转自:http://blog.csdn.net/yihongyuelan/article/details/7216188

http://www.zzgjj.com/

及一样首文章:Android中先后与Service交互的法——综述
简述了Service的组成部分基础知识以及Service和Thread的简要区别,本文将重点讲解与Service交互的五种为主方法:广播交互、共享文件交互、Mssenger(信使)交互、自定义接口交互、AIDL交互。

 

       1.
播放交互

 

      
提到Activity与Service的彼此,可能狠多口第一想到的哪怕是BroadCast——广播。在Android中,广播是系提供的一样栽死好之交互方式。比如:在电池电量过没有,开机完成等情事下,系统都见面有相应的系统广播,我们的应用程序只待注册相应的播音接收器,就得接到及这些网的播报。同时,我们为得定义自己的广播,这样于不同之Activity、Service以及应用程序之间,就足以经过广播来贯彻相互之间。我们通过模拟应用程序后台下载的情形来分析Service与Activity的交互方式。实现效益使图1.1:

宅院公积金贷款须知

澳门新莆京赌场网站app 1

http://www.zzgjj.com/typenews.asp?id=152

图1.1

 

       
当我们点击StartService按钮之后,界面及之快漫漫将会各隔一秒加1。因为是仿下载,因此下载动作我们在Service中经一个Timer定时器来兑现,在Timer中对一个整型数据i进行自加(i++),然后Client端获取Server端的i值并出示在界面上,从而达到模拟的目的。

 两人:身份证、户口本、结婚证、
      身份证复印件-》查征信记录
      房管局-》无房证
      收入证明
      最终做房贷时 两人数与
主贷款人:在郑社保、银行流水

        1.1.
实现原理

 

       
Server端将手上底下载快,通过播放的章程发送出,Client端注册之广播的监听器,当得到该广播后,将播放中时的下载快解析出并更新到界面上。

 

        1.2.
兑现步骤

金水区房管局  同笑路9声泪俱下        63979622

        1.2.1
在Client端中经startService()啟动Service。

 

 

[java] view
plaincopyprint?

  1. if(v == startBtn){  
  2.     Log.i(TAG, “start button clicked…pid: “+Process.myPid());  
  3.     mIntent.setClass(BroadCastService.this, DownLoadService.class);  
  4.     startService(mIntent);  
  5. }  

if(v == startBtn){ Log.i(TAG, “start button clicked…pid:
“+Process.myPid()); mIntent.setClass(BroadCastService.this,
DownLoadService.class); startService(mIntent); }

          这里的mIntent = new
Intent();Process.myPid()方法可拿走当前过程的ID号。
       1.2.2
DownLoadService接到启动的吩咐后,执行onCreate()方法,并以其中被timer计数模拟下载。

 

 

[java] view
plaincopyprint?

  1. @Override  
  2. public void onCreate() {  
  3.     super.onCreate();  
  4.     Log.i(TAG, “DownLoadService.onCreate()…pid: “+Process.myPid());  
  5.     intent = new Intent(“com.seven.broadcast”);  
  6.     mTimer = new Timer();  
  7.     mTimer.schedule(new MyTimerTask(), 0 , TIME * 1000);  
  8. }  

@Override public void onCreate() { super.onCreate(); Log.i(TAG,
“DownLoadService.onCreate()…pid: “+Process.myPid()); intent = new
Intent(“com.seven.broadcast”); mTimer = new Timer(); mTimer.schedule(new
MyTimerTask(), 0 , TIME * 1000); }

          这里的intent是Server端向Client端传送数据用之,使用的action是”com.seven.broadcast”,Client端只有註册了相应action才会吸纳至Server端的播放,并分析其中的始末。Process.myPid()是沾当前历程的ID。
        1.2.3
在Server端的timer计数其中发送广播,告知Client端目前产充斥进度。

 

 

[java] view
plaincopyprint?

  1. class MyTimerTask extends TimerTask{  
  2.     @Override  
  3.     public void run() {  
  4.         if(i==100){  
  5.             i=0;  
  6.         }  
  7.         intent.putExtra(“CurrentLoading”, i);  
  8.         sendBroadcast(intent);  
  9.         i++;  
  10.         Log.e(TAG, “i= “+i);  
  11.     }  
  12. }  

class MyTimerTask extends TimerTask{ @Override public void run() {
if(i==100){ i=0; } intent.putExtra(“CurrentLoading”, i);
sendBroadcast(intent); i++; Log.e(TAG, “i= “+i); } }

          通过intent.putExtra(key,value);设置intent的值,然后通过sendBroadcast(intent)2智,将播发送出。

 

       1.2.4
在Client端通过匿名内部类的道实例化BroadcastReceiver并覆写其中的onReceive()方法。

 

[java] view
plaincopyprint?

  1. BroadcastReceiver receiver = new BroadcastReceiver() {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         if(MYACTION.equals(intent.getAction())){  
  5.             Log.i(TAG, “get the broadcast from DownLoadService…”);  
  6.             curLoad = intent.getIntExtra(“CurrentLoading”, ERROR);  
  7.             mHandler.sendMessage(mHandler.obtainMessage());  
  8.         }  
  9.     }  
  10. };  

BroadcastReceiver receiver = new BroadcastReceiver() { @Override public
void onReceive(Context context, Intent intent) {
if(MYACTION.equals(intent.getAction())){ Log.i(TAG, “get the broadcast
from DownLoadService…”); curLoad =
intent.getIntExtra(“CurrentLoading”, ERROR);
mHandler.sendMessage(mHandler.obtainMessage()); } } };

         
在onReceive()方法吃,判断是否也Server端发送的广播,如果是虽然指向播音中带走的intent数据进行解包处理。这裡也得以单独写一个类似继承自BroadcastReceiver,在其间覆写onReceive()方法,在Client端中实例化其目标,同样好直达相应的功力,这样做足啊后实现静态注册广播。
        1.2.5 更新主介面下载进度。

 

 

[java] view
plaincopyprint?

  1. Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         Log.i(TAG, “current loading: “+curLoad);  
  6.         if(curLoad<0||curLoad>100){  
  7.             Log.e(TAG, “ERROR: “+curLoad);  
  8.             return;  
  9.         }  
  10.         mProgressBar.setProgress(curLoad);  
  11.         mTextView.setText(curLoad+”%”);  
  12.     }  
  13. };  

Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); Log.i(TAG,
“current loading: “+curLoad); if(curLoad<0||curLoad>100){
Log.e(TAG, “ERROR: “+curLoad); return; }
mProgressBar.setProgress(curLoad); mTextView.setText(curLoad+”%”); } };

             这里针对得到之进度进行了一致破判断,如果获到的价没有好,那么用会晤显得到界面,并更新速度久之快慢,如果大则归。
         1.2.6
一定要是针对Broadcast进行登记和注销注册。只有注册后相应的broadcast之后才能够接受及广播注册方式发生三三两两种植。
         动态注册/取消注册:

 

 

[java] view
plaincopyprint?

  1. @Override  
  2. protected void onResume() {  
  3.     super.onResume();  
  4.     Log.i(TAG, “register the broadcast receiver…”);  
  5.     IntentFilter filter = new IntentFilter();  
  6.     filter.addAction(MYACTION);  
  7.     registerReceiver(receiver, filter);  
  8. }  
  9. @Override  
  10. protected void onDestroy() {  
  11.     super.onDestroy();  
  12.     Log.i(TAG, “unregister the broadcast receiver…”);  
  13.     unregisterReceiver(receiver);  
  14. }  

@Override protected void onResume() { super.onResume(); Log.i(TAG,
“register the broadcast receiver…”); IntentFilter filter = new
IntentFilter(); filter.addAction(MYACTION); registerReceiver(receiver,
filter); } @Override protected void onDestroy() { super.onDestroy();
Log.i(TAG, “unregister the broadcast receiver…”);
unregisterReceiver(receiver); }

           动态註册可以随时註册随时取消。

 

       
静态註册:

 

[html] view
plaincopyprint?

  1. <receiver android:name=”MyBroadcastReceiver”>  
  2.     <intent-filter>  
  3.         <action android:name=”com.seven.broadcast” />  
  4.     </intent-filter>  
  5. </receiver>  

<receiver android:name=”MyBroadcastReceiver”>
<intent-filter> <action android:name=”com.seven.broadcast”
/> </intent-filter> </receiver>

           注:这里的MyBroadcastReceiver是一个累自BroadcastReceiver的类。静态注册只要报了扳平软那么要该次没有被卸载那么该广播将一直有效。

 

       
最后贴发出总体AndroidManifest.xml文件

 

[html] view
plaincopyprint?

  1. <application android:icon=”@drawable/icon” android:label=”@string/app_name”>  
  2.     <activity android:name=”.BroadCastService”  
  3.               android:label=”@string/app_name”>  
  4.         <intent-filter>  
  5.             <action android:name=”android.intent.action.MAIN” />  
  6.             <category android:name=”android.intent.category.LAUNCHER” />  
  7.         </intent-filter>  
  8.     </activity>  
  9.     <service android:name=”DownLoadService” android:process=”:remote”/>  
  10. </application>  

<application android:icon=”@drawable/icon”
android:label=”@string/app_name”> <activity
android:name=”.BroadCastService” android:label=”@string/app_name”>
<intent-filter> <action
android:name=”android.intent.action.MAIN” /> <category
android:name=”android.intent.category.LAUNCHER” />
</intent-filter> </activity> <service
android:name=”DownLoadService” android:process=”:remote”/>
</application>

          这里的android:process
=”:remote”可以使该Service运行在独进程面临,从而得以如法炮制过进程通信。

 

       1.3
小结

      
通过播放的方法实现Activity与Service的互动操作简易且容易实现,可以胜任简单级的施用。但缺点也很明了,发送广播中系统制约。系统会优先发送系统级广播,在某些特定的景象下,我们打定义的播放可能会见延迟。同时于播放接收器中不可知处理长耗时操作,否则系统会产出ANR即应用程序无响应。

        2.
共享文件交互

       
这里涉及的共享文件指的是Activity和Service使用与一个文件来上传递数据的目的。我们下SharedPreferences来促成共享,当然也得以以其他IO方法实现,通过这种办法贯彻相互之间时要留意,对于文本的读写的时刻,同一时间只能一正值宣读一正值形容,不能够少正在同时写。实现效益使图2.1:

澳门新莆京赌场网站app 2

图2.1

         2.1
实现原理

        
Server端将眼前下充斥进度写副共享文件中,Client端通过读取共享文件被的下载快,并创新至主界面上。

         2.2
实现步骤

         2.2.1
在Client端通过startService()啟动Service。

 

[java] view
plaincopyprint?

  1. if(startSerBtn==v){  
  2.     Log.i(TAG, “Start Button Clicked.”);  
  3.     if(intent!=null){  
  4.     startService(intent);  
  5.     timer.schedule(new MyTimerTask(), 0, TIME * 1000);  
  6.     }  
  7. }  

if(startSerBtn==v){ Log.i(TAG, “Start Button Clicked.”);
if(intent!=null){ startService(intent); timer.schedule(new
MyTimerTask(), 0, TIME * 1000); } }

          这里的intent = new
Intent()2不过是为启动Server端。
        2.2.2
Server端收到启动intent之后执行onCreate()方法,并拉开timer,模拟下载,以及初始化SharedPreferences对象preferences。

 

 

[java] view
plaincopyprint?

  1. @Override  
  2. public void onCreate() {  
  3.     super.onCreate();  
  4.     Log.i(TAG, “DownLoadService.onCreate()…”);  
  5.     preferences = getSharedPreferences(“CurrentLoading_SharedPs”, 0);  
  6.     timer = new Timer();  
  7.     timer.schedule(new MyTimerTask(), 0, TIME*1000);  
  8. }  

@Override public void onCreate() { super.onCreate(); Log.i(TAG,
“DownLoadService.onCreate()…”); preferences =
getSharedPreferences(“CurrentLoading_SharedPs”, 0); timer = new
Timer(); timer.schedule(new MyTimerTask(), 0, TIME*1000); }

          通过preferences=getSharedPreferences(String,MODE)2可以在/data/data/com.seven.servicetestdemo/shared_prefs文件夹下建立相应的xml文件。

 

       2.2.3
开始计数并以下充斥进度写副shared_prefs文件夹下的xml文件被,内容以键值对之方法保留。

 

[java] view
plaincopyprint?

  1. class MyTimerTask extends TimerTask{  
  2.     @Override  
  3.     public void run() {  
  4.         setCurrentLoading();  
  5.         if(100==i){  
  6.             i=0;  
  7.         }  
  8.         i++;  
  9.     }         
  10. }     
  11. private void setCurrentLoading() {  
  12.     preferences.edit().putInt(“CurrentLoading”, i).commit();  
  13. }  

class MyTimerTask extends TimerTask{ @Override public void run() {
setCurrentLoading(); if(100==i){ i=0; } i++; } } private void
setCurrentLoading() { preferences.edit().putInt(“CurrentLoading”,
i).commit(); }

           对於SharedPreferences的运得专注一下几乎接触:

 

       
首先,使用sharedPreferences前待获得文件引用。

       
preferences = getSharedPreferences(“CurrentLoading_SharedPs”,
0);

       
其次,使用sharedpreferences写多少方式。

       
preferences.edit().putInt(“CurrentLoading”, i).commit();

       
最后,读取数据的法。

        int
couLoad = preferences.getInt(“CurrentLoading”, 0);

        2.2.4
Client端通过读取/data/data/com.seven.servicetestdemo/shared_prefs文件夹下的xml文件,并取得里面的键值对,从而赢得到即之下载快,并创新至主界面上。

 

[java] view
plaincopyprint?

  1. Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         int couLoad = preferences.getInt(“CurrentLoading”, 0);  
  6.         mProgressBar.setProgress(couLoad);  
  7.         currentTv.setText(couLoad+”%”);  
  8.     }  
  9.  };  

Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); int couLoad =
preferences.getInt(“CurrentLoading”, 0);
mProgressBar.setProgress(couLoad); currentTv.setText(couLoad+”%”); } };

          2.3 小结

 

       
因為方法简单,因此便非糊出AndroidManifest.xml文件了。对於这种办法实现Activity与Service的互相,可以说坏有益,就如以管道,一个朝着裡写,一个通往外读。但这种方式啊时有发生通病,写副数据比较复杂与数据量较生时,就发生或导致写副与读数据产生非同等的不当。同时为经了一个中转站,这种操作将再耗时。

        3.
Messenger交互(信使交互)

       
Messenger翻译过来指的凡信使,它引用了一个Handler对象,别人能向它发送信息(使用mMessenger.send(Message
msg)方法)。该类允许超过进程间基于Message通信,在服务端使用Handler创建一个
Messenger,客户端只要取得是服务端的Messenger对象就是可同服务端通信了。也就是说我们可以管Messenger当做Client端与Server端的传话筒,这样虽足以沟通交流了。实现效益使图3.1:

澳门新莆京赌场网站app 3

图3.1

        3.1
实现原理

       
在Server端与Client端之间通过一个Messenger对象来传递消息,该对象类似于信息中转站,所有信息经过该对象携带。

        3.2
Messenger的一般用法

        (1).
在Server端创建信使对象。

              
mMessenger = new Messenger(mHandler)

        (2).
Client端使用bindService()绑定Server端。

        (3).
Server端的onBind()方法返回一个binder对象。

              
return mMessenger.getBinder();

        (4).
Client端使用返回的binder对象获得Server端信使。

 

[java] view
plaincopyprint?

  1. public void onServiceConnected(ComponentName name, IBinder service) {    
  2.               rMessenger = new Messenger(service);        
  3.              ……  
  4.  }  

public void onServiceConnected(ComponentName name, IBinder service) {
rMessenger = new Messenger(service);      …… }

          这里虽是new了一个Messenger,但咱查阅她的实现

 

 

[java] view
plaincopyprint?

  1. public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target);  }   

public Messenger(IBinder target) { mTarget =
IMessenger.Stub.asInterface(target); }

           发现她的mTarget是通过AIDL得到的,实际上即便是远程创建的可怜。

 

        (5).
Client端可以行使这Server端的投递员对象为Server端发送信息。
               rMessenger.send(msg);

       
这样Server端的Handler对象就会接到信息了,然后可以当该handlerMessage(Message
msg)方法中展开拍卖。经过及时5单步骤之后只有Client端向Server端发送信息,这样的消息传递是只有为的,那么哪些落实信息之双向传送呢?

       
首先要以第5步做修改,在send(msg)前透过msm.replyTo =
mMessenger将Client端自己之投递员设置及信息中,这样Server端接收至消息不时以为落了Client端的投递员对象,然后Server端也可以经动用得的Client端的投递员对象来项Client端发送信息
cMessenger = msg.replyTo2  cMessenger.send(message);

      
这样尽管成功了起Server端向Client端发送信息之成效,这样Client端可以当协调的Handler对象的handlerMessage()方法被接到服务端发送来之message进行拍卖。

        3.3
实现步骤

        3.3.1
创建并初始化Server端的通信员对象。

 

[java] view
plaincopyprint?

  1. private Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         switch (msg.what) {  
  6.         case TEST:  
  7.             Log.e(TAG, “Get Message from MainActivity.”);  
  8.             cMessenger = msg.replyTo;  
  9.             mTimer.schedule(new MyTimerTask(), 1000,TIME * 1000);  
  10.             break;  
  11.             default:  
  12.                 break;  
  13.             }  
  14.         }         
  15. };  
  16. //It’s the messenger of server   
  17. private Messenger mMessenger = new Messenger(mHandler);  

private Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what)
{ case TEST: Log.e(TAG, “Get Message from MainActivity.”); cMessenger =
msg.replyTo; mTimer.schedule(new MyTimerTask(), 1000,TIME * 1000);
break; default: break; } } }; //It’s the messenger of server private
Messenger mMessenger = new Messenger(mHandler);

          3.3.2
在Client端使用bindService()方法绑定Server端。

 

 

[java] view
plaincopyprint?

  1. private void doBindService(){  
  2.         Log.i(TAG, “doBindService()…”);  
  3.     mIsBind = bindService(intent, serConn, BIND_AUTO_CREATE);//if bind success return true   
  4.         Log.e(TAG, “Is bind: “+mIsBind);  
  5. }  

private void doBindService(){ Log.i(TAG, “doBindService()…”); mIsBind
= bindService(intent, serConn, BIND_AUTO_CREATE);//if bind success
return true Log.e(TAG, “Is bind: “+mIsBind); }

          3.3.3
在Server端的onBind()方法中归一个binder对象。

 

 

[java] view
plaincopyprint?

  1. @Override  
  2. public IBinder onBind(Intent intent) {  
  3.     Log.i(TAG, “MessengerService.onBind()…”);  
  4.     return mMessenger.getBinder();  
  5. }  

@Override public IBinder onBind(Intent intent) { Log.i(TAG,
“MessengerService.onBind()…”); return mMessenger.getBinder(); }

         
这裡的mMessenger就是Server端的投递员对象。

 

        3.3.4
Client端使用ServiceConnected()方法来得到Server端的投递员对象。

 

[java] view
plaincopyprint?

  1. private ServiceConnection serConn = new ServiceConnection() {     
  2.     @Override  
  3.     public void onServiceDisconnected(ComponentName name) {  
  4.         Log.i(TAG, “onServiceDisconnected()…”);  
  5.         rMessenger = null;  
  6.     }         
  7.     @Override  
  8.     public void onServiceConnected(ComponentName name, IBinder service) {  
  9.         Log.i(TAG, “onServiceConnected()…”);  
  10.     rMessenger = new Messenger(service);//get the object of remote service   
  11.     mMessenger = new Messenger(mHandler);//initial the object of local service   
  12.     sendMessage();  
  13.     }  
  14. };  

private ServiceConnection serConn = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) { Log.i(TAG,
“onServiceDisconnected()…”); rMessenger = null; } @Override public
void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, “onServiceConnected()…”); rMessenger = new
Messenger(service);//get the object of remote service mMessenger = new
Messenger(mHandler);//initial the object of local service sendMessage();
} };

           获取Server端的投递员对象的还要,也初始化Client端的友好之投递员对象,并且经过sendMessage()方法发送信息被Server端,表示可以起来下载了。

 

        3.3.5
Client端使用得到之rMessenger来发送信息被Server端,同时用Client端的通信员封装到信息遭到,一并发送给Server端。

 

[java] view
plaincopyprint?

  1. private void sendMessage() {  
  2.     Message msg = Message.obtain(null, MessengerService.TEST);//MessengerService.TEST=0   
  3.     msg.replyTo = mMessenger;  
  4.     try {  
  5.         rMessenger.send(msg);  
  6.     } catch (RemoteException e) {  
  7.         e.printStackTrace();  
  8.     }  
  9. }  

private void sendMessage() { Message msg = Message.obtain(null,
MessengerService.TEST);//MessengerService.TEST=0 msg.replyTo =
mMessenger; try { rMessenger.send(msg); } catch (RemoteException e) {
e.printStackTrace(); } }

           这里的MessengerService.TEST為Server端里的一个静态常量。Msg.replyTo=mMessenger;表示发送给Server端的信息里携带Client端的通信员。

 

        3.3.6
Server端获取Client端发送的音信并赢得Client端的通信员对象。

 

[java] view
plaincopyprint?

  1. private Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         switch (msg.what) {  
  6.         case TEST:  
  7.             Log.e(TAG, “Get Message from MainActivity.”);  
  8.             cMessenger = msg.replyTo;//get the messenger of client   
  9.             mTimer.schedule(new MyTimerTask(), 1000,TIME * 1000);  
  10.             break;  
  11.         default:  
  12.             break;  
  13.         }  
  14.     }  
  15. };  

private Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what)
{ case TEST: Log.e(TAG, “Get Message from MainActivity.”); cMessenger =
msg.replyTo;//get the messenger of client mTimer.schedule(new
MyTimerTask(), 1000,TIME * 1000); break; default: break; } } };

           在收及Client端的信息后,Server端开啟timer模拟下载,并接收Client端的通信员对象。

 

        3.3.7
Server端向Client端发送数据。

 

[java] view
plaincopyprint?

  1. class MyTimerTask extends TimerTask {  
  2.     @Override  
  3.     public void run() {  
  4.         if (i == 100) {  
  5.             i = 0;  
  6.         }  
  7.         try {  
  8.             //send the message to the client
      
  9.         Message message = Message.obtain(null, MessengerService.TEST,i, 0);  
  10.             cMessenger.send(message);  
  11.         } catch (RemoteException e) {  
  12.                 e.printStackTrace();  
  13.         }  
  14.             i++;  
  15.     }  
  16. }  

class MyTimerTask extends TimerTask { @Override public void run() { if
(i == 100) { i = 0; } try { //send the message to the client Message
message = Message.obtain(null, MessengerService.TEST,i, 0);
cMessenger.send(message); } catch (RemoteException e) {
e.printStackTrace(); } i++; } }

         
直接利用收取至之Client端的投递员对象来发送当前下充斥进度给Client端。

 

        3.3.8
Client端接收来自Server端的多寡。

 

[java] view
plaincopyprint?

  1. private Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         switch (msg.what) {  
  6.         case MessengerService.TEST:  
  7.             Log.e(TAG, “Get Message From MessengerService. i= “+msg.arg1);  
  8.             int curLoad = msg.arg1;  
  9.             mTextView.setText(curLoad+”%”);  
  10.             mProgressBar.setProgress(curLoad);  
  11.             break;  
  12.         default:  
  13.             break;  
  14.         }  
  15.     }  
  16. };  

private Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what)
{ case MessengerService.TEST: Log.e(TAG, “Get Message From
MessengerService. i= “+msg.arg1); int curLoad = msg.arg1;
mTextView.setText(curLoad+”%”); mProgressBar.setProgress(curLoad);
break; default: break; } } };

           Client端的收到和Server端的收狠类似。接收至Server端传过来的数目后展开介面更新,以及下载快更新。

 

       
以下是AndroidManifest.xml文件:

 

[html] view
plaincopyprint?

  1. <?xml version=”1.0″ encoding=”utf-8″?>  
  2. <manifest xmlns:android=”http://schemas.android.com/apk/res/android”  
  3.       package=”com.seven.messengerservicedemo”  
  4.       android:versionCode=”1″  
  5.       android:versionName=”1.0″>  
  6.     <uses-sdk android:minSdkVersion=”10″ />  
  7.     <application android:icon=”@drawable/icon” android:label=”@string/app_name”>  
  8.         <activity android:name=”.MainActivity”  
  9.                   android:label=”@string/app_name”>  
  10.             <intent-filter>  
  11.                 <action android:name=”android.intent.action.MAIN” />  
  12.                 <category android:name=”android.intent.category.LAUNCHER” />  
  13.             </intent-filter>  
  14.         </activity>  
  15.     <service android:name=”MessengerService”>  
  16.         <intent-filter>  
  17.     <action ndroid:name=”com.seven.messagerservice.MessengerService” />  
  18.         </intent-filter>  
  19.     </service>  
  20. </application>  
  21. </manifest>  

<?xml version=”1.0″ encoding=”utf-8″?> <manifest
xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.seven.messengerservicedemo” android:versionCode=”1″
android:versionName=”1.0″> <uses-sdk android:minSdkVersion=”10″
/> <application android:icon=”@drawable/icon”
android:label=”@string/app_name”> <activity
android:name=”.MainActivity” android:label=”@string/app_name”>
<intent-filter> <action
android:name=”android.intent.action.MAIN” /> <category
android:name=”android.intent.category.LAUNCHER” />
</intent-filter> </activity> <service
android:name=”MessengerService”> <intent-filter> <action
ndroid:name=”com.seven.messagerservice.MessengerService” />
</intent-filter> </service> </application>
</manifest>

           这里以Service的註册中在了过滤动作,只生相匹配的action才会启动相应的Service。

 

        3.4
小结

       
通过Messenger来实现Activity和Service的并行,稍微尖锐一些我们不怕得清楚,其实Messenger也是透过AIDL来落实之。对於前少栽实现方式,Messenger方式总体达成来讲也是于易于掌握的,这便和平时采用Handler和Thread通信一个理。

        4.
从定义接口交互

       
何谓自定义接口也,其实就是是咱团结一心通过接口的落实来达到Activity与Service交互的目的,我们经过当Activity和Service之间架设一所桥樑,从而达成数交互的目的,而这种实现方式及AIDL非常类似(后文会说交)。实现力量使图4.1:

澳门新莆京赌场网站app 4

图4.1

        4.1
实现原理

       
自定义一个接口,该接口中有一个到手当前生充斥进度的空方法。Server端用一个看似继承自Binder并促成该接口,覆写了间获得当前下充斥进度的措施。Client端通过ServiceConnection获取到此类的对象,从而能够使用该得到当前产卵充斥进度的方式,最终兑现实时互动。

        4.2
实现步骤

        4.2.1
新建一个Interface,并于中间创建一个用来获取当前产充斥进度的底空方法getCurrentLoad()。

 

[java] view
plaincopyprint?

  1. package com.seven.servicetestdemo;  
  2.   
  3. public interface ICountService {  
  4.     public int getCurrentLoad();  
  5. }  

package com.seven.servicetestdemo; public interface ICountService {
public int getCurrentLoad(); }

        4.2.2
新建Server端DownService实现ICountService并当内部通过一个内部类ServiceBinder继承自Binder并促成ICoutService接口。

 

 

[java] view
plaincopyprint?

  1. public class DownLoadService extends Service implements ICountService{  
  2. private ServiceBinder serviceBinder = new ServiceBinder();    
  3. public class ServiceBinder extends Binder implements ICountService{  
  4.     @Override  
  5.     public int getCurrentLoad() {  
  6.         Log.i(TAG, “ServiceBinder getCurrentLoad()… i=:”+i);  
  7.         return i;  
  8.     }     
  9. }  
  10. @Override  
  11. public int getCurrentLoad() {  
  12.     return 0;  
  13. }  
  14. }  

public class DownLoadService extends Service implements ICountService{
private ServiceBinder serviceBinder = new ServiceBinder(); public class
ServiceBinder extends Binder implements ICountService{ @Override public
int getCurrentLoad() { Log.i(TAG, “ServiceBinder getCurrentLoad()…
i=:”+i); return i; } } @Override public int getCurrentLoad() { return 0;
} }

         
在Server端中,实现获取下充斥进度的空方法getCurrentLoad();这是Eclipse自动生成的,重点不在这裡。我们要以ServiceBinder类中覆写getCurrentLoad()方法,这裡我们回去时底下载进度i。

 

       4.2.3
Client端使用bindService()绑定Server端。

 

[java] view
plaincopyprint?

  1. if (startSerBtn == v) {  
  2.     Log.i(TAG, “Start Button Clicked.”);  
  3.     bindService(intent, serConn, BIND_AUTO_CREATE);  
  4.     timer.schedule(new MyTimerTask(), 1000, TIME * 1000);//这里肯定要是延缓一下重复起来获取数据,不然会报空指针异常
      
  5. }  

if (startSerBtn == v) { Log.i(TAG, “Start Button Clicked.”);
bindService(intent, serConn, BIND_AUTO_CREATE); timer.schedule(new
MyTimerTask(), 1000, TIME *
1000);//这里肯定要是延期一下又开始获取数据,不然会报空指针异常 }

           在Client端绑定Server端的又,延迟1s起获得下充斥进度。其中的intent
= new
Intent(“com.seven.test”)2com.seven.test欠字符串要跟以AndroidManifest.xml中阐明的一致。

 

       4.2.4
Server端返回binder对象。

 

[java] view
plaincopyprint?

  1. @Override  
  2. public IBinder onBind(Intent intent) {  
  3.     Log.i(TAG, “DownLoadService.onBind()…”);  
  4.     return serviceBinder;  
  5. }  

@Override public IBinder onBind(Intent intent) { Log.i(TAG,
“DownLoadService.onBind()…”); return serviceBinder; }

           这里的serviceBinder因为累了Binder因此也是Binder对象。

 

        4.2.5
Client端通过ServiceConnection来获取Server端的binder对象。

 

[java] view
plaincopyprint?

  1. private ServiceConnection serConn = new ServiceConnection() {  
  2. @Override  
  3.     public void onServiceDisconnected(ComponentName name) {  
  4.         iCountService = null;  
  5.     }         
  6.     @Override  
  7.     public void onServiceConnected(ComponentName name, IBinder service) {  
  8.         Log.i(TAG, “onServiceConnected()…”);  
  9.         iCountService = (ICountService)service;  
  10.     }  
  11. };  

private ServiceConnection serConn = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) { iCountService =
null; } @Override public void onServiceConnected(ComponentName name,
IBinder service) { Log.i(TAG, “onServiceConnected()…”); iCountService
= (ICountService)service; } };

         
获取的进程是于bindService()过程被得的,这里的iCountService是接口ICountService的靶子,在这里得到实例化。

 

        4.2.6
在绑定好之后,Server端会开启下载,在其实情况中Server端会开启独立线程用于下载,这里用i++来代替。

 

[java] view
plaincopyprint?

  1. @Override  
  2. public void onCreate() {  
  3.     super.onCreate();  
  4.     Log.i(TAG, “DownLoadService.onCreate()…”);  
  5.     timer = new Timer();  
  6.     timer.schedule(new MyTimerTask(), 0, TIME*1000);  
  7. }  
  8. class MyTimerTask extends TimerTask{  
  9.     @Override  
  10.     public void run() {  
  11.         if(100==i){  
  12.             i=0;  
  13.         }  
  14.         i++;  
  15.     }  
  16. }  

@Override public void onCreate() { super.onCreate(); Log.i(TAG,
“DownLoadService.onCreate()…”); timer = new Timer();
timer.schedule(new MyTimerTask(), 0, TIME*1000); } class MyTimerTask
extends TimerTask{ @Override public void run() { if(100==i){ i=0; } i++;
} }

         
bindService()方法执行下会调用DownLoadService中的onCreate()方法,在其onCreate()方法吃被timer使得i++。

 

        4.2.7
Server端已经打开了下载,那么Client端需要及时获取下充斥进度并以主界面上更新。

 

[java] view
plaincopyprint?

  1. Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         Log.i(TAG, “handleMessage…”);  
  6.         int curLoad = iCountService.getCurrentLoad();  
  7.         mProgressBar.setProgress(curLoad);  
  8.         currentTv.setText(curLoad+”%”);  
  9.     }  
  10.  };  
  11. class MyTimerTask extends TimerTask{  
  12.     @Override  
  13.     public void run() {  
  14.         mHandler.sendMessage(mHandler.obtainMessage());  
  15.     }  
  16. }  

Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); Log.i(TAG,
“handleMessage…”); int curLoad = iCountService.getCurrentLoad();
mProgressBar.setProgress(curLoad); currentTv.setText(curLoad+”%”); } };
class MyTimerTask extends TimerTask{ @Override public void run() {
mHandler.sendMessage(mHandler.obtainMessage()); } }

           Client端的Timer在bindService()完成后1秒再开取下充斥进度,获取方式是直接通过int
curLoad =
iCountService.getCurrentLoad();这里的getCurrentLoad()方法是DownLoadService内部类ServiceBinder中的法门。Client端将得到到之下载快更新至介面上连更新速度漫长。

 

        4.3
小结

       
通过者的事例可以解,这种措施简便实用,扩展性强,但其为来一对败笔,比如用延期一些重新开得到Server端的数量,从而无法完全落实从零开始同步创新。综其所述,通过由定义接口实现Activity与Service交互的点子还是比实用的。适用於同进程中通信,不可知开展超越进程通信。

        5.
AIDL交互

       
什么是AIDL?

       
AIDL是Android Interface Definition Language的首字母缩写,
也不怕是Android接口定义语言。提及AIDL就只能说下Android的服务,Android
支持有限栽服务类型的劳务就地面服务与远程服务。

       
本地服务无法供在配备及运行的另应用程序访问,也就是说只能该应用程序内部调用,比如一些应用程序中之下载类服务,这些服务只能由其中调用。而对于远程服务,除了可由本应用程序调用,还得允许其他应用程序访问。远程服务一般经过AIDL来落实,可以进行过程中通信,这种劳动也就是长途服务。

       
本地服务同长途服务还是有局部要的分别。具体来讲,如果服务完全只供同一进程面临的组件使用(运行后台任务),客户端一边通过调用
Context.startService()来启动该服务。这种类型的劳动啊当地服务,它的貌似用是后台执行长耗时操作。而远程服务一般经过bindService()方法启动,主要为不同进程中通信。我们吧用长途服务称为AIDL支持服务,因为客户端应用
AIDL
与服务通信。Android中对此远程服务来多种叫法:远程服务、AIDL服务、外部服务和RPC服务。

        5.1
AIDL实现流程图

澳门新莆京赌场网站app 5

图5.1

       
这属于代理/存根结构,通过这张AIDL的流程图,很爱发觉Android实现IPC其实是以原先的C/S框架上进入了代办/存根结构。

       
比如,你及自动取款机上去取款。那么你就算是客户(Client),取款机就是公的代理(Proxy);你切莫见面在乎钱实际在那里,你只有想拿你的钱从取款机中拿走下。你与银行之间的操作了是取款机代理实现。你的取款请求通过取款机传到其他一面,即银行的服务器(Server)。它呢从来不必要了解你在哪里得到钱,它所关切的是若的身价以及公取款多少。当它们肯定你的权杖,就进行相应的操作,返回操作结果让取款机,取款机根据服务器返回结果,从保险柜里取出相应数据之钱给您。你拿走出卡后,操作完。取款机不是直接和服务器连接的,他们中间还有一个“存根(Stub)”,取款机与存根通信,服务器和存根通信,从某种意义上说存根就是服务器的代办。实现力量使图5.2:

澳门新莆京赌场网站app 6

图5.2

        5.3
实现原理

       
AIDL属于Android的IPC机制,常用于跨进程通信,主要实现原理基于底层Binder机制。

        5.4
实现步骤

        5.4.1
建立工程。按照图5.3以及图5.4建立AIDLServer端以及AIDLClient端。在AIDLServer端中单单生一个服务程序,没有主界面,其重要功用就是是肩负下载。AIDLClient端从AIDLServer端获取当前生充斥进度(注:AIDLServer端和AIDLClient端是例外的星星个APK,在模仿本例的时光,需要先在模拟器上安装AIDLServer编译出的APK,安装方式可以一直当模拟器上运行一次等,可以由此adb
install your.apk 来装)。

澳门新莆京赌场网站app 7

图5.3

       
AIDLServer端中新建了一个ICountService.aidl的文书,该公文内容如下:

 

[plain] view
plaincopyprint?

  1. package com.seven.aidlserver;  
  2.   
  3. interface ICountService{  
  4.     int getCount();  
  5. }  

package com.seven.aidlserver; interface ICountService{ int getCount(); }

          aidl文件之题规范如下:

 

        (1).
Android支持String和CharSequence(以及Java的中心数据类);

        (2).
如果用在aidl中使外aidl接口类型,需要import,即使是于同样包结构下;

        (3).
Android允许传递实现Parcelable接口的切近,需要import;

        (4).
Android支持集合接口类型List和Map,但是生一对限量,元素必须是基本型或者前面三栽状况,不需import集合接口类,但是得针对素涉及到之花色import;

        (5).
非基本数据类,也未是String和CharSequence类型的,需要发倾向指示,包括in、out和inout,in表示出于客户端设置,out表示是因为服务端设置,inout是双边都只是安装。

澳门新莆京赌场网站app 8

图5.4

        
AIDLClient端需要用AIDLServer端的ICountService.aidl文件复製过去,这裡为了便利,新建了一个及Server端同名的管,并拿ICountService.aidl放与其间。

         5.4.2
我们以Server端建立好ICoutService.aidl文件从此,Eclipse会在/gen/com.seven.aidlserver/目录下自动生成ICountService.java文件。该文件由Eclipse自动生成,请无随便修改,后文我们用引用到的情如下:

 

[java] view
plaincopyprint?

  1. public static com.seven.aidlserver.ICountService asInterface(android.os.IBinder obj) {  
  2.     if ((obj == null)) {  
  3.         return null;  
  4.     }  
  5. android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);  
  6.     if (((iin != null) && (iin instanceof com.seven.aidlserver.ICountService))) {  
  7.         return ((com.seven.aidlserver.ICountService) iin);  
  8.     }  
  9.     return new com.seven.aidlserver.ICountService.Stub.Proxy(obj);  
  10. }  

public static com.seven.aidlserver.ICountService
asInterface(android.os.IBinder obj) { if ((obj == null)) { return null;
} android.os.IInterface iin = (android.os.IInterface)
obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin
instanceof com.seven.aidlserver.ICountService))) { return
((com.seven.aidlserver.ICountService) iin); } return new
com.seven.aidlserver.ICountService.Stub.Proxy(obj); }

          5.4.3
在Server端新建一个里头类继承自ICountService.Stub并覆写其中的getCount()方法,以及实例化该类的一个目标serviceBinder。

 

 

[java] view
plaincopyprint?

  1. private AIDLServerBinder serviceBinder = new AIDLServerBinder();  
  2. class AIDLServerBinder extends ICountService.Stub{  
  3.     @Override  
  4.     public int getCount() throws RemoteException {  
  5.         return i;  
  6.     }  
  7. }  

private AIDLServerBinder serviceBinder = new AIDLServerBinder(); class
AIDLServerBinder extends ICountService.Stub{ @Override public int
getCount() throws RemoteException { return i; } }

        
这里跟前提到的“通过接口实现相互之间”非常接近。

 

        5.4.4
在Server端的onBind()方法吃,返回前面的serviceBinder对象。

 

[java] view
plaincopyprint?

  1. @Override  
  2. public IBinder onBind(Intent intent) {  
  3.     Log.i(TAG, “AIDLServer.onBind()…”);  
  4.     return serviceBinder;  
  5. }  

@Override public IBinder onBind(Intent intent) { Log.i(TAG,
“AIDLServer.onBind()…”); return serviceBinder; }

         5.4.5
在Server端的onCreate()方法吃,开启timer,模拟下载。在Client端通过bindService()绑定Server端的早晚,会率先实施Server端的onCreate()方法。

 

 

[java] view
plaincopyprint?

  1. @Override  
  2. public void onCreate() {  
  3.     super.onCreate();  
  4.     Log.i(TAG, “AIDLServer.onCreate()…”);  
  5.     mTimer = new Timer();  
  6.     mTimer.schedule(new MyTimerTask(), 0,TIME * 1000);  
  7. }  
  8. class MyTimerTask extends TimerTask{  
  9.     @Override  
  10.     public void run() {  
  11.         if(i==100){  
  12.             i=0;  
  13.         }  
  14.         i++;  
  15.     }  
  16. }  

@Override public void onCreate() { super.onCreate(); Log.i(TAG,
“AIDLServer.onCreate()…”); mTimer = new Timer(); mTimer.schedule(new
MyTimerTask(), 0,TIME * 1000); } class MyTimerTask extends TimerTask{
@Override public void run() { if(i==100){ i=0; } i++; } }

          5.4.6
Client端通过bindService()绑定Server端。

 

 

[java] view
plaincopyprint?

  1. if(startBtn==v){  
  2.     Log.i(TAG, “start button click.”);  
  3.     mIsBind = bindService(intent, serConn, BIND_AUTO_CREATE);  
  4.     mTimer.schedule(new MyTimerTask(), 1000 ,TIME * 1000);  
  5. }  

if(startBtn==v){ Log.i(TAG, “start button click.”); mIsBind =
bindService(intent, serConn, BIND_AUTO_CREATE); mTimer.schedule(new
MyTimerTask(), 1000 ,TIME * 1000); }

          这里的intent = new
Intent(“com.seven.aidlserver”);这里跟Server端注册Service时过滤的使平等,也就是说只有产生同样的action才会启动该Service。同时开了一个timer用于获取下充斥进度。
        5.4.7
Client端通过ServiceConnection来获取Server端的binder对象。

 

 

[java] view
plaincopyprint?

  1. private ServiceConnection serConn = new ServiceConnection() {         
  2.     @Override  
  3.     public void onServiceDisconnected(ComponentName name) {  
  4.         iCountService = null;  
  5.     }         
  6.     @Override  
  7.     public void onServiceConnected(ComponentName name, IBinder service) {  
  8.         Log.i(TAG, “AIDLClient.onServiceConnected()…”);  
  9.         iCountService = ICountService.Stub.asInterface(service);  
  10.     }  
  11. };  

private ServiceConnection serConn = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) { iCountService =
null; } @Override public void onServiceConnected(ComponentName name,
IBinder service) { Log.i(TAG, “AIDLClient.onServiceConnected()…”);
iCountService = ICountService.Stub.asInterface(service); } };

          这里的iCountService对象实际即便是ICountService的对象在斯实例化。

 

        5.4.8
获取当前生充斥进度并创新到界面上。

 

[java] view
plaincopyprint?

  1. Handler mHandler = new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         try {  
  6.             int count =  iCountService.getCount();  
  7.             mTextView.setText(count+”%”);  
  8.             mProgressBar.setProgress(count);  
  9.         } catch (RemoteException e) {  
  10.             e.printStackTrace();  
  11.         }  
  12.     }  
  13. };  

Handler mHandler = new Handler(){ @Override public void
handleMessage(Message msg) { super.handleMessage(msg); try { int count =
iCountService.getCount(); mTextView.setText(count+”%”);
mProgressBar.setProgress(count); } catch (RemoteException e) {
e.printStackTrace(); } } };

         
通过创新介面上之进度长,可以狠容易的继去时产充斥进度。因為AIDLServer端只是一个连续自Service的劳务,因此尽管不贴出其AndroidManifest.xml文件了。

 

        5.5
小结

       
AIDL在Android中凡是经过之中通信常用之法子,可能使较為复杂,但效率高,扩展性好。同时多体系服务就是是盖这种方式形成与应用程序通信的。

       
本文通过五个例证,分别介绍了五种植和Service交互的道,这些主意有简单易行,有的可能使复杂一些。在此地只是做为对Servie的一部分总。后文附上源码下充斥链接,不需要积分的哦。:D

       
源码下载

       
所有源码均于Ubuntu 10.04 Eclipse-Indigo下实验通过
模拟器采用的凡2.3底镜像

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注