package com.service.service; import com.example.service.R; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.widget.Toast; /** * service組件 * 1.定義一個類繼承Service類 * Service兩種啓動方式 * <1>.start * <2>.onBind * 服務對象同時只有一個 * 默認狀況下,一個started的service與啓動它的應用組件在同一線程中, * 因此若是咱們使用service來完成一些好使的操做任務時,就會阻塞主線程 * 那咱們就必須在線程中來處理耗時任務 * 中止一個服務的兩種方法 * <1>.在外部使用stopService() * <2>.在服務類內部使用stopSelf() * * IntentService * 該類型的service會在單獨的線程中執行任務,任務完成後會自動結束service * 當咱們有須要這樣一次性完成的任務就可使用IntentService來完成 * * * * IPC(進程間的通信) * AIDL(android接口定義語言) * 使用aidl定義業務接口,經過ADT工具來生成一個java類,此類實現了進程間遠程通信的代理 * 編寫本身的業務類(繼承生成的類中的stub存根)來實現業務接口 * 再經過綁定service的方式來暴露此業務對象給其餘組件提供功能 * * 調用者組件經過servuce方法綁定服務,從而能夠獲取綁定成功後的遠程業務對象或本地對象 * 能夠調用相關的功能 * 注意:通常在使用完綁定服務後,須要解除綁定 * * 自定義AIDL對象 * 1.須要自自定義的類型上實現Parcelable接口 * 2.須要定義一個aidl文件來申明自定義類型(在student。aidl文件中申明 parcelable Student;) * 3.在使用該自定義類型時必須使用import語句導入該自定義類型,不然報錯 * * * * 使用started與bing服務之間的區別 * 使用started會一直運行在後臺,須要服務自己或外部組件中止服務纔會結束運行 * 經過bind的服務,它的生命週期依賴綁定的組件, * 1.started服務能夠給啓動的對象傳遞參數,但沒法獲取服務中的方法返回 * 2.能夠給啓動的服務對象傳遞參數,也能夠經過綁定的業務對象獲取返回結果 * 在實際應用中的使用技巧 * 1.第一次先使用started來啓動一個服務, * 以後可使用綁定的方式綁定服務,從而能夠直接調用業務方法返回值 * */ public class MainActivity extends Activity { private IPerson person; //要使用的業務對象接口 boolean flag=false; //服務鏈接對象 private ServiceConnection serviceConnection=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub //當服務異常終止時會調用,注意:解除綁定服務時不會調用 System.out.println("onServiceDisconnected"); flag=false; } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub //綁定成功後服務會回調該方法,自動傳入IBinder對象 System.out.println("onServiceConnected"); person= IPerson.Stub.asInterface(service); System.out.println(person); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * 啓動一個服務 * */ public void start1(View view){ System.out.println("start1"); Intent intent=new Intent(this,HelloService.class); startService(intent); } public void stop(View view){ System.out.println("stop"); Intent intent=new Intent(this,HelloService.class); stopService(intent); } public void start2(View view){ Intent intent=new Intent(this,HelloIntentService.class); startService(intent); } //綁定一個服務 public void bindService(View view){ System.out.println("bindService"); Intent intent=new Intent(this,MyService.class); //參數(1.intent對象,2.服務鏈接對象,3.綁定服務的標記) flag=bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } //解除綁定服務 public void unBindService(View view){ if(flag){ unbindService(serviceConnection); flag=false; } } //調用遠程業務對象方法(或是本地業務) public void callPerson(View view) throws RemoteException{ person.setName("張三"); person.setAge(21); person.setSex("男"); String s=person.getPerson(); Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show(); }
activity_main.xmljava
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.service.service.MainActivity" android:orientation="vertical" > <Button android:id="@+id/activity1_button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="啓動service1" android:onClick="start1" /> <Button android:id="@+id/activity1_button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="中止service1" android:onClick="stop" /> <Button android:id="@+id/activity1_button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="startIntentService" android:onClick="start2" /> <Button android:id="@+id/activity1_button4" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="綁定Service" android:onClick="bindService" /> <Button android:id="@+id/activity1_button5" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="解綁Service" android:onClick="unBindService" /> <Button android:id="@+id/activity1_callPerson" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="調用業務對象Person的方法" android:onClick="callPerson" /> </LinearLayout>
HelloService
android
package com.service.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class HelloService extends Service{ private PersonImpl personImpl; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return new PersonImpl(); } //建立服務時調用 @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.i("HelloService", "HelloServiceOnCreate"); } //銷燬服務時調用 @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.i("HelloService", "HelloServiceONDestory"); } //服務執行時的操做 @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.i("HelloService", "HelloServiceONStartCommand"); System.out.println("HelloServiceONStartCommand"); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub int i=0; for(;i<10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //HelloService.this.stopSelf(); //中止服務 } }).start(); return super.onStartCommand(intent, flags, startId); } }
IPerson.aidl文件
安全
package com.service.service; interface IPerson { void setName(String name); void setSex(String sex); void setAge(int age); String getPerson(); }
PersonImpl
app
package com.service.service; import android.os.RemoteException; public class PersonImpl extends IPerson.Stub { private String name; private String sex; private int age; @Override public void setName(String name) throws RemoteException { // TODO Auto-generated method stub this.name=name; } @Override public void setSex(String sex) throws RemoteException { // TODO Auto-generated method stub this.sex=sex; } @Override public void setAge(int age) throws RemoteException { // TODO Auto-generated method stub this.age=age; } @Override public String getPerson() throws RemoteException { // TODO Auto-generated method stub return "name="+name+"sex="+sex+"age="+age; } }
第二種:繼承IntentServiceide
HelloIntentService
工具
package com.service.service; import android.app.IntentService; import android.content.Intent; public class HelloIntentService extends IntentService{ public HelloIntentService() { super("IntentSerice"); // TODO Auto-generated constructor stub } //該方法會在一個單獨的線程中執行,來完成工做任務 //任務結束後,該service會自動中止 @Override protected void onHandleIntent(Intent intent) { // TODO Auto-generated method stub for(int i=0;i<10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); System.out.println("OnDestory"); } }
全部的service須要在清單文件中申明this
<service android:name="com.service.service.HelloService"></service>spa
<service android:name="com.service.service.HelloIntentService"></service>線程
使用onBind方式代理
package com.service.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; /** * 實現一個綁定服務 * * */ public class MyService extends Service{ private PersonImpl personImpl; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); System.out.println("MyServiceOnCreate()"); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub System.out.println("MyServiceOnBind()"); personImpl=new PersonImpl(); return personImpl; } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub System.out.println("MyServiceOnUnBind()"); return super.onUnbind(intent); } }
自定義AIDL
IStudent.aidl
package com.service.service; import com.service.service.Student; interface IStudent { void setStudnet(String name,String sex); Student getStudent(); }
Student.aidl
parcelable Student;
Student
package com.service.service; import android.os.Parcel; import android.os.Parcelable; public class Student implements Parcelable{ private String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated method stub dest.writeString("name"); dest.writeString("sex"); } public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() { public Student createFromParcel(Parcel in) { Student student=new Student(); student.setName(in.readString()); student.setSex(in.readString()); return student; } public Student[] newArray(int size) { return new Student[size]; } }; }
StudentImpl
package com.service.service; import android.os.RemoteException; /** * 業務對象的實現 * */ public class StudentImpl extends IStudent.Stub{ private Student student; public StudentImpl(){ student=new Student(); } @Override public void setStudnet(String name, String sex) throws RemoteException { // TODO Auto-generated method stub this.student.setName(name);; this.student.setSex(sex); } @Override public Student getStudent() throws RemoteException { // TODO Auto-generated method stub return student; } }
StudentService
package com.service.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class StudentService extends Service{ private StudentImpl studentImpl; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub studentImpl=new StudentImpl(); return studentImpl; } }
使用Messenge
MessageService
package com.service.service; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.widget.Toast; public class MessageService extends Service{ static final int MSG_HELLO=0x1; private Handler handler=new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case MSG_HELLO: Toast.makeText(MessageService.this, "hello", Toast.LENGTH_SHORT).show(); break; default: break; } }; }; private Messenger messenger=new Messenger(handler); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return messenger.getBinder(); } }
MessageActivity
package com.service.service; import com.example.service.R; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.view.View; /** * 使用Messenger實現IPC, * 1.Messenger是線程安全的,在service中建立一個Messenger對象並綁定一個handle * 2.在onBind方法中返回messenger對象,經過messenger的getIBinder方法返回一個IBinder對象 * 3.在調用的組件中,ServiceConnection的onServiceConnection時間中,根據IBinder對象來建立一個Messenger對象 * 這樣兩個Messenger對象就同事綁定到一個IBinder對象上,從而能夠底線通訊, * 在調用組件中方法種使用Messenger的send方法來發送消息到service的Messenger對象中 * */ public class MessageActivity extends Activity{ private Messenger messenger; private boolean mBound=false; private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub if(mBound){ mBound=false; } } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub messenger=new Messenger(service); mBound=true; } }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.message_main); } public void useMessenger(View view){ Message message=Message.obtain(); message.what=MessageService.MSG_HELLO; try { messenger.send(message); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); Intent intent=new Intent(this,MessageService.class); bindService(intent, conn, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); if(mBound){ unbindService(conn); mBound=false; } } }
清單文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.service" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.service.service.MessageActivity" 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="com.service.service.HelloService"></service> <service android:name="com.service.service.HelloIntentService"></service> <service android:name="com.service.service.MyService" android:process=":remote"></service> <service android:name="com.service.service.StudentService"></service> <service android:name="com.service.service.MessageService"></service> </application> </manifest> <!-- android:process=":remote"設置運行在本身的進程中 -->