zoukankan      html  css  js  c++  java
  • Android Service

    Android 有四大组件: Activity , Service , BroadcastReceiver , ContentProvider, 这篇主要讲Service

    启动Service有两种方式: startService 和 bindService

    startService:

      Service也有自己的生命周期, startService是会依次调用service的 onCreate(), onStartCommand(),onStart()方法(实际在父类的onStartCommand()方法中主动调用的onStart()),如果Service已经启动了,则只会调用onStartCommand()和onStart().

      stopService,停止已经开始的Service,会动用Service的onDestroy();

      从log中可以看到,Service是运行与主线程,所以不应做繁重的任务,防止ANR.

    bindService:

      bindService 需要传三个参数 Intent ,ServiceConnection , flag

        Intent 指明需要启动的Service ; ServiceConnection Service连接成功之后的回调; flag bind的方式,一般是1;

      bindService 会依次调用Service的onCreate(),onBind()方法, 如果Service已经启动,再次bindService会连接,但不会再调用生命周期的方法

      unbindService 会调用Service的onDestroy()。

      通过bindService的方式启动Service,可以获取到一个IBinder对象,通过IBinder对象可以调用Service里的方法。

      binderService的第二个参数: 通过onServiceConnected()回调 可以获取到IBinder对象。

     1     ServiceConnection sc = new ServiceConnection() {
     2         @Override
     3         public void onServiceDisconnected(ComponentName name) {
     4             
     5         }
     6         @Override
     7         public void onServiceConnected(ComponentName name, IBinder service) {
     8             // TODO Auto-generated method stub
     9 
    10     };

    AIDL: android 接口定义语言,通过他可以实现进程间的通信。

    要和远端的Service进行交互,可以使用aidl实现进程间的通信:

    myService.aidl

    1 package com.example.servicelearning.aidl;
    2 
    3 interface myService {
    4     void register();
    5     int get();
    6 }

    编译之后,会在gen目录对应包名下自动生成一个myService.java的接口,里面有一个内部静态抽象类Stub,实现了myService的接口。

    编译之后的myService.java

      1 /*
      2  * This file is auto-generated.  DO NOT MODIFY.
      3  * Original file: E:\vivoCamera\ServiceLearning\src\com\example\servicelearning\aidl\myService.aidl
      4  */
      5 package com.example.servicelearning.aidl;
      6 public interface myService extends android.os.IInterface
      7 {
      8 /** Local-side IPC implementation stub class. */
      9 public static abstract class Stub extends android.os.Binder implements com.example.servicelearning.aidl.myService
     10 {
     11 private static final java.lang.String DESCRIPTOR = "com.example.servicelearning.aidl.myService";
     12 /** Construct the stub at attach it to the interface. */
     13 public Stub()
     14 {
     15 this.attachInterface(this, DESCRIPTOR);
     16 }
     17 /**
     18  * Cast an IBinder object into an com.example.servicelearning.aidl.myService interface,
     19  * generating a proxy if needed.
     20  */
     21 public static com.example.servicelearning.aidl.myService asInterface(android.os.IBinder obj)
     22 {
     23 if ((obj==null)) {
     24 return null;
     25 }
     26 android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
     27 if (((iin!=null)&&(iin instanceof com.example.servicelearning.aidl.myService))) {
     28 return ((com.example.servicelearning.aidl.myService)iin);
     29 }
     30 return new com.example.servicelearning.aidl.myService.Stub.Proxy(obj);
     31 }
     32 @Override public android.os.IBinder asBinder()
     33 {
     34 return this;
     35 }
     36 @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
     37 {
     38 switch (code)
     39 {
     40 case INTERFACE_TRANSACTION:
     41 {
     42 reply.writeString(DESCRIPTOR);
     43 return true;
     44 }
     45 case TRANSACTION_register:
     46 {
     47 data.enforceInterface(DESCRIPTOR);
     48 this.register();
     49 reply.writeNoException();
     50 return true;
     51 }
     52 case TRANSACTION_get:
     53 {
     54 data.enforceInterface(DESCRIPTOR);
     55 int _result = this.get();
     56 reply.writeNoException();
     57 reply.writeInt(_result);
     58 return true;
     59 }
     60 }
     61 return super.onTransact(code, data, reply, flags);
     62 }
     63 private static class Proxy implements com.example.servicelearning.aidl.myService
     64 {
     65 private android.os.IBinder mRemote;
     66 Proxy(android.os.IBinder remote)
     67 {
     68 mRemote = remote;
     69 }
     70 @Override public android.os.IBinder asBinder()
     71 {
     72 return mRemote;
     73 }
     74 public java.lang.String getInterfaceDescriptor()
     75 {
     76 return DESCRIPTOR;
     77 }
     78 @Override public void register() throws android.os.RemoteException
     79 {
     80 android.os.Parcel _data = android.os.Parcel.obtain();
     81 android.os.Parcel _reply = android.os.Parcel.obtain();
     82 try {
     83 _data.writeInterfaceToken(DESCRIPTOR);
     84 mRemote.transact(Stub.TRANSACTION_register, _data, _reply, 0);
     85 _reply.readException();
     86 }
     87 finally {
     88 _reply.recycle();
     89 _data.recycle();
     90 }
     91 }
     92 @Override public int get() throws android.os.RemoteException
     93 {
     94 android.os.Parcel _data = android.os.Parcel.obtain();
     95 android.os.Parcel _reply = android.os.Parcel.obtain();
     96 int _result;
     97 try {
     98 _data.writeInterfaceToken(DESCRIPTOR);
     99 mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0);
    100 _reply.readException();
    101 _result = _reply.readInt();
    102 }
    103 finally {
    104 _reply.recycle();
    105 _data.recycle();
    106 }
    107 return _result;
    108 }
    109 }
    110 static final int TRANSACTION_register = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    111 static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    112 }
    113 public void register() throws android.os.RemoteException;
    114 public int get() throws android.os.RemoteException;
    115 }
    View Code

    在自己的Service 实现此类里面的抽象方法。在bindService的时候,onBind()方法可以return此对象,通过此对象实现通信。

    BindServiceTest.java  (记得在Manifest文件里声明Service)

     1 package com.example.servicelearning.service;
     2 
     3 import com.example.servicelearning.aidl.myService;
     4 
     5 import android.app.Service;
     6 import android.content.Intent;
     7 import android.os.IBinder;
     8 import android.os.RemoteException;
     9 import android.util.Log;
    10 
    11 public class BindServiceTest extends Service {
    12     
    13     
    14     private static final String TAG = "BindServiceTestLog.TAG";
    15 
    16     
    17     myService.Stub mStub = new myService.Stub() {
    18         
    19         @Override
    20         public void register() throws RemoteException {
    21             // TODO Auto-generated method stub
    22             Log.d(TAG, "register from com.example.servicelearning");
    23         }
    24         
    25         @Override
    26         public int get() throws RemoteException {
    27             // TODO Auto-generated method stub
    28             return 10086;
    29         }
    30     };
    31     
    32     @Override
    33     public IBinder onBind(Intent intent) {
    34         Log.d(TAG, "onBind");
    35         return mStub;
    36     }
    37 
    38  }

     

      为了验证通过AIDL实现的进程通信,我们可以再编写一个apk,通过这个apk启动之前那个apk里面的Service,并实现通信。

      在这个apk里面我们必须写一个同样的aidl文件,包名必须和之前那个一致。

    MainActivity.java   (布局文件和Manifest文件都比较简单就不贴出来了)

     1 package com.example.servicetesthelp;
     2 
     3 import com.example.servicelearning.aidl.myService;
     4 import android.app.Activity;
     5 import android.content.ComponentName;
     6 import android.content.Context;
     7 import android.content.Intent;
     8 import android.content.ServiceConnection;
     9 import android.os.Bundle;
    10 import android.os.IBinder;
    11 import android.os.RemoteException;
    12 import android.util.Log;
    13 import android.view.View;
    14 import android.view.View.OnClickListener;
    15 import android.widget.Button;
    16 
    17 public class MainActivity extends Activity {
    18 
    19     private static final String TAG = "MainActivityLog.TAG";
    20     Button mButton;
    21     @Override
    22     protected void onCreate(Bundle savedInstanceState) {
    23         super.onCreate(savedInstanceState);
    24         setContentView(R.layout.activity_main);
    25         mButton = (Button) findViewById(R.id.mButton);
    26         mButton.setOnClickListener(new OnClickListener() {
    27             
    28             @Override
    29             public void onClick(View v) {
    30                 // TODO Auto-generated method stub
    31                 Log.d(TAG, "onClick ");
    32                 Intent mIntent = new Intent("android.service.bindservicetest");
    33                 mIntent.setPackage("com.example.servicelearning");
    34                 bindService(mIntent, new ServiceConnection() {
    35                     
    36                     @Override
    37                     public void onServiceDisconnected(ComponentName name) {
    38                         // TODO Auto-generated method stub                        
    39                     }
    40                     
    41                     @Override
    42                     public void onServiceConnected(ComponentName name, IBinder service) {
    43                         // TODO Auto-generated method stub
    44                         Log.d(TAG , "ServiceTestHelp  onServiceConnected");
    45                         myService binder = myService.Stub.asInterface(service);
    46                         try {
    47                             binder.register();
    48                             Log.d(TAG," get = " + binder.get());
    49                         } catch (RemoteException e) {
    50                             // TODO Auto-generated catch block
    51                             e.printStackTrace();
    52                         }
    53                     }
    54                 }, Context.BIND_AUTO_CREATE);
    55             }
    56         });
    57     }
    58 
    59 }
    View Code

      点击按钮之后,启动Service,(启动Service时,Intent必须是显性的),onServiceConnected()方法的回调的Ibinder方法,通过myService.Stub.asInterface()方法获取到myService对象,通过此对象可以调用对端Service的方法,具体可以通过Log看到。

    1 01-06 08:07:30.385 30401 30401 D MainActivityLog.TAG: onClick
    2 01-06 08:07:30.450 30442 30442 D BindServiceTestLog.TAG: onBind 3 01-06 08:07:30.452 30401 30401 D MainActivityLog.TAG: ServiceTestHelp onServiceConnected 4 01-06 08:07:30.453 30442 30462 D BindServiceTestLog.TAG: register from com.example.servicelearning 5 01-06 08:07:30.454 30401 30401 D MainActivityLog.TAG: get = 10086

       可以看到是在两个进程里面,也可以正常通信。

  • 相关阅读:
    [转载] 常用CASE工具介绍
    GridView, DataGrid 中,DataFormatString语法汇总
    [轉]SQL Server中数据类型详解
    强烈推荐asp.net数据访问的官方指南系列 (Data Access Tutorials)
    实现iFrame自适应高度,原来很简单!
    [转]Web service到底是什么?在什么情况下,你应该使用web service
    贴一个查询SQL Server数据库中所有表及其描述(Description)的SQL语句
    C#中,String和string的区别
    ERWin 连接SQL Sever2005的问题
    [转载]ERwin相关概念入门
  • 原文地址:https://www.cnblogs.com/xiaojianli/p/5651138.html
Copyright © 2011-2022 走看看