打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
[z]android?service?使用以及aidl使用

android service 使用以及aidl使用

(2011-05-08 10:50:53)
service

1:service的启动方式
service是一个在后台运行的服务。你所启动的这个service所做得工作最好在另一个线程中做。因为这个service的线程的工作将阻塞调用它的线程。
创建和启动一个service有两种方式
Intent in = new Intent(***);
startService(in) 和 bindService(in)。
与上面相对应,停止一个service也有两种方式
stopService(in)  和 unbindService(in)。

如果是本地的service 则 Intent in = newIntent(this,LocalService.class)。同时那个service要在manifest文件中标明自己的name
<service android:name =".serviceA"/>

如果是非本地的service 则在Intent中指明就可以了Intent in= new Intent("com.test.A")与此同时那个非本地的service也要在manifest文件中申明自己的name和intent-filter
   <service android:name =".serviceA">
           <intent-filter>
              <actionandroid:name="com.test.A"/>
              <categoryandroid:name="android.intent.category.DEFAULT"/>
          </intent-filter>
       </service>



2:使用startService 和stopService
这种启动和停止方式是比较简单的。只需要在调用Activity中直接写上就可以了。

2.1service客户端代码
调用service的客户端的activity的代码:
package com.D_activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;


public class D_activity extends Activity {
    Buttonb;
    privateboolean running =  false;
   @Override
    public voidonCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
   //设置一个按钮来开启和关闭服务
       b=(Button)findViewById(R.id.button);
    }
   @Override
    protectedvoid onResume() {
//指定一个Intent
      final Intent in = new Intent("com.test.A");
       super.onResume();
       b.setOnClickListener(new OnClickListener(){

           @Override
           public void onClick(View v) {
               if(running){
                   running = false;
      //关闭服务
                   stopService(in);
                   b.setText("start ");
               }
               else{
                   running = true;
      //开启服务
                   startService(in);
                   b.setText("stop");
               }
           }
           
       });
    }
}


2.2被startService()调用的service 的代码:
通过startService启动的service在service的生命周期中将调用:onCreate()->onStartCommand()->onDestory()。
onCreate仅仅在第一次创建这个service的时候调用。onStartCommand会在你使用startService()后调用。onDestory会在你使用stopSerivce的时候调用。

以下代码将实现一个每5秒打印系统时间的service,多半代码都是从文档中直接拿过来的。
package com.A_s;

import java.text.SimpleDateFormat;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.os.Process;
import android.widget.Toast;

public class serviceA extends Service {

    privateboolean flag =true;
    privateLooper mServiceLooper;
    privateServiceHandler mServiceHandler;

    // Handlerthat receives messages from the thread
    privatefinal class ServiceHandler extends Handler {
       public ServiceHandler(Looper looper) {
           super(looper);
       }
       @Override
       public void handleMessage(Message msg) {
           // Normally we would do some work here, like download a file.
           // For our sample, we just sleep for 5 seconds.
           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss");
           while(flag){
               synchronized (this) {
                     try {
                         Log.i("TEST","A :"+sdf.format(System.currentTimeMillis()));
                         wait(5*1000);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
               }
         }
           // Stop the service using the startId, so that we don't stop
           // the service in the middle of handling another job
           stopSelf(msg.arg1);
       }
    }

   @Override
    public voidonCreate() {
     // Start up the thread running the service.  Notethat we create a
     // separate thread because the service normally runs in theprocess's
     // main thread, which we don't want to block.  Wealso make it
     // background priority so CPU-intensive work will not disrupt ourUI.
     HandlerThread thread = newHandlerThread("ServiceStartArguments",
             Process.THREAD_PRIORITY_BACKGROUND);
     thread.start();
     
     // Get the HandlerThread's Looper and use it for our Handler
     mServiceLooper = thread.getLooper();
     mServiceHandler = new ServiceHandler(mServiceLooper);
    }

   @Override
    public int onStartCommand(Intent intent, intflags, int startId) {
       Toast.makeText(this, "service starting",Toast.LENGTH_SHORT).show();

       // For each start request, send a message to start a job anddeliver the
       // start ID so we know which request we're stopping when we finishthe job
       Message msg = mServiceHandler.obtainMessage();
       msg.arg1 = startId;
       mServiceHandler.sendMessage(msg);
       
       // If we get killed, after returning from here, restart
       return START_STICKY;
    }

   @Override
    publicIBinder onBind(Intent intent) {
       // We don't provide binding, so return null
       return null;
    }
    
   @Override
    public voidonDestroy() {
     Toast.makeText(this, "service done",Toast.LENGTH_SHORT).show();
     flag =false;
    }
}


Manifest文件:
<service android:name =".serviceA">
           <intent-filter>
              <actionandroid:name="com.test.A"/>
              <categoryandroid:name="android.intent.category.DEFAULT"/>
          </intent-filter>
       </service>



3:使用bindService和unbindService
这种方式启动的service生命周期中将调用:onCreate()->onBind()->onDestory()。
在service中与之前startService最不同的一点是,这次service不再使用onStartCommand而是使用onBind.所以这次service的代码与上面service的不同仅仅在于把onStartCommand的逻辑代码放到onBind中就可以了。
 @Override
    publicIBinder onBind(Intent intent) {
       // We don't provide binding, so return null
       Toast.makeText(this, "service starting in onBind",Toast.LENGTH_SHORT).show();
       Message msg = mServiceHandler.obtainMessage();
       mServiceHandler.sendMessage(msg);

       return IBind;
    }




3.1使用bindService的客户端的代码如下

这次的Activity明显比之前使用startService的Activity多了一点东西,就是多了ServiceConnection类。当bindService完成时,系统会自动调用ServiceConnection中的onServiceConnected()
package com.C_activity;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class C_activity extends Activity {
    Buttonb;
    privateboolean running =  false;
    
   @Override
    public voidonCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       b=(Button)findViewById(R.id.button);
      
    }
   @Override
    protectedvoid onResume() {
      final Intent in = new Intent("com.test.E");
       super.onResume();
       b.setOnClickListener(new OnClickListener(){

           @Override
           public void onClick(View v) {
               if(running){
                   running = false;
                   unbindService(sc);
                   b.setText("start ");
               }
               else{
                   running = true;
//bindService方法的最后一个参数有其特定的意义,最好找文档确定自己需要哪种
                   bindService(in,sc, 1);
                   b.setText("stop");
               }
           }
           
       });
    }
    
    
    private ServiceConnection sc = newServiceConnection(){

       @Override
       public void onServiceConnected(ComponentName name, IBinder service){
           
       }

       @Override
       public void onServiceDisconnected(ComponentName name){   
         
   };
    
}

4:利用aidl 远程调用service
当service不是本地的服务,也就不能通过onServiceConnected中的IBinder来强制转换成相应服务类来使用service提供的一些方法。这时就需要使用aidl了。
直观的去看,远程服务如果能够被操作,也需要提供一个操作的接口,而这个接口不光在服务器端实现,同时在客户端也需要知道调用和使用的方式;因此我们需要定义aidl文件来描述这么一个服务,也就是通过双方共享一个aidl文件的方式来共享一个接口。
在aidl里面定义了这个接口的内容之后,android的IDE帮助编译自动生成一个相应名字的java文件。这个java里面生成一个接口:test_aidl (extendsandroid.os.IInterface) ,
 同时,最主要的,里面有个桩: public static abstract class Stubextends android.os.Binder implements test_aidl

比如我写了一个叫test_aidl.aidl的文件 内容如下:
package com.E_s;
 interfacetest_aidl{
   int getCount();
 }
那么在工程的gen目录下会自动生成一个test_aidl.java文件。然后在service中你就可以使用并实现这个接口中的方法。

 private finaltest_aidl.Stub IBind = new test_aidl.Stub()      
       @Override
       public int getCount() throws RemoteException {
           // TODO Auto-generated method stub
           return i;
       }
    };

4.1使用aidl的service端的全部代码如下:
package com.E_s;

import java.text.SimpleDateFormat;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.os.Process;
import android.widget.Toast;

public class serviceA extends Service {
    
    privateboolean flag =true;
    privateLooper mServiceLooper;
    privateServiceHandler mServiceHandler;
    publicstatic int i = 0;

    // Handlerthat receives messages from the thread
    privatefinal class ServiceHandler extends Handler {
       public ServiceHandler(Looper looper) {
           super(looper);
       }
       @Override
       public void handleMessage(Message msg) {
           // Normally we would do some work here, like download a file.
           // For our sample, we just sleep for 5 seconds.
           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss");
           while(flag){
               synchronized (this) {
                     try {
                         i++;
                         Toast.makeText(serviceA.this, "E_s",Toast.LENGTH_SHORT).show();
                         Log.i("liyufei","E(A) :"+sdf.format(System.currentTimeMillis()));
                         wait(5*1000);
                     } catch (InterruptedException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
               }
         }
           // Stop the service using the startId, so that we don't stop
           // the service in the middle of handling another job
//           stopSelf(msg.arg1);
       }
    }

   @Override
    public voidonCreate() {
     // Start up the thread running the service.  Notethat we create a
     // separate thread because the service normally runs in theprocess's
     // main thread, which we don't want to block.  Wealso make it
     // background priority so CPU-intensive work will not disrupt ourUI.
     HandlerThread thread = newHandlerThread("ServiceStartArguments",
             Process.THREAD_PRIORITY_BACKGROUND);
     thread.start();
     
     // Get the HandlerThread's Looper and use it for our Handler
     mServiceLooper = thread.getLooper();
     mServiceHandler = new ServiceHandler(mServiceLooper);
    }

   @Override
    publicIBinder onBind(Intent intent) {
       Toast.makeText(this, "service starting in onBind",Toast.LENGTH_SHORT).show();

       Message msg = mServiceHandler.obtainMessage();
       mServiceHandler.sendMessage(msg);

       return IBind;
    }
    
    private final test_aidl.Stub IBind = newtest_aidl.Stub() {
       
       @Override
       public int getCount() throws RemoteException {
           return i;
       }
   };
    
   @Override
    public voidonDestroy() {
     Toast.makeText(this, "service done",Toast.LENGTH_SHORT).show();
     flag =false;
    }
}


在客户端,你首先要在客户端的工程中也创建相应的包名和aidl文件。比如将文中的test_aidl.aidl也放入客户端的com.E_s包中。然后客户端中也会自动生成一个test_aidl.java文件
然后就只需要将之前的使用bindService的客户端代码中的ServiceConnection方法中添加些东西就好了。
    test_aidltestAidl;

   private ServiceConnection sc =new ServiceConnection(){
       @Override
       public void onServiceConnected(ComponentName name, IBinder service){
           testAidl = test_aidl.Stub.asInterface(service);
       }
       @Override
       public void onServiceDisconnected(Com
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android的IPC机制(一)——AIDL的使用
android进程间通信:使用AIDL
4.2.3 Service精通
android service
android service入门
aidl 中通过RemoteCallbackList 运用到的回调机制: service回调activity的方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服