1.Service的start和bind状态有什么区别?
2.同一个service,先start然后bindService,如何把它停止调?
3.serviceCommand方法的返回值的不同含义是什么?
4.service的生命周期方法onCreate,onStart,onBind等运行在哪个线程?
1
start和启动它的组件没有关系,它有自己独立的生命周期,而bindService这个service依赖于这些组件,当这些组件全部销毁候,service也随之销毁。
多次调用start方法,start方法会多次被回调,多次调用bind,bind只会执行一次。
start开启的servic必须stopService或者stopSelf后停止,bind的service可以用unbind去停止服务、
2
stopService和每个绑定它的组件unBindService,最后一个stopService或者unBindService会导致service destroy.
3
/** * Bits returned by {@link #onStartCommand} describing how to continue * the service if it is killed. May be {@link #START_STICKY}, * {@link #START_NOT_STICKY}, {@link #START_REDELIVER_INTENT}, * or {@link #START_STICKY_COMPATIBILITY}. */ public static final int START_CONTINUATION_MASK = 0xf; /** * Constant to return from {@link #onStartCommand}: compatibility * version of {@link #START_STICKY} that does not guarantee that * {@link #onStartCommand} will be called again after being killed. */ public static final int START_STICKY_COMPATIBILITY = 0; /** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started (after returning from * {@link #onStartCommand}), then leave it in the started state but * don't retain this delivered intent. Later the system will try to * re-create the service. Because it is in the started state, it will * guarantee to call {@link #onStartCommand} after creating the new * service instance; if there are not any pending start commands to be * delivered to the service, it will be called with a null intent * object, so you must take care to check for this. * * <p>This mode makes sense for things that will be explicitly started * and stopped to run for arbitrary periods of time, such as a service * performing background music playback. */ public static final int START_STICKY = 1; /** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started (after returning from * {@link #onStartCommand}), and there are no new start intents to * deliver to it, then take the service out of the started state and * don't recreate until a future explicit call to * {@link Context#startService Context.startService(Intent)}. The * service will not receive a {@link #onStartCommand(Intent, int, int)} * call with a null Intent because it will not be re-started if there * are no pending Intents to deliver. * * <p>This mode makes sense for things that want to do some work as a * result of being started, but can be stopped when under memory pressure * and will explicit start themselves again later to do more work. An * example of such a service would be one that polls for data from * a server: it could schedule an alarm to poll every N minutes by having * the alarm start its service. When its {@link #onStartCommand} is * called from the alarm, it schedules a new alarm for N minutes later, * and spawns a thread to do its networking. If its process is killed * while doing that check, the service will not be restarted until the * alarm goes off. */ public static final int START_NOT_STICKY = 2; /** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started (after returning from * {@link #onStartCommand}), then it will be scheduled for a restart * and the last delivered Intent re-delivered to it again via * {@link #onStartCommand}. This Intent will remain scheduled for * redelivery until the service calls {@link #stopSelf(int)} with the * start ID provided to {@link #onStartCommand}. The * service will not receive a {@link #onStartCommand(Intent, int, int)} * call with a null Intent because it will will only be re-started if * it is not finished processing all Intents sent to it (and any such * pending events will be delivered at the point of restart). */ public static final int START_REDELIVER_INTENT = 3;
4
运行在主线程中
下面是我学习用aidl写的一个start和bind service的一个示例
// Book1.aidl package com.example.administrator.myaidl.aidl; // Declare any non-default types here with import statements parcelable Book;
package com.example.administrator.myaidl.aidl; import com.example.administrator.myaidl.aidl.Book; // Declare any non-default types here with import statements interface IBookArrivedListener { void onNewBookArrived(in Book book); }
package com.example.administrator.myaidl.aidl; // Declare any non-default types here with import statements import com.example.administrator.myaidl.aidl.Book; import com.example.administrator.myaidl.aidl.IBookArrivedListener; interface IBookManager { List<Book> getBookList(); void addBook(in Book book); void registerNewBookArrivedListener(in IBookArrivedListener bookArrivedListenre); void unRegisterNewBookArrivedListener(in IBookArrivedListener bookArrivedListenre); }
package com.example.administrator.myaidl.aidl; import android.os.Parcel; import android.os.Parcelable; public class Book implements Parcelable{ public int bookId; public String bookName; public Book(int bookId,String bookName){ this.bookId = bookId; this.bookName = bookName; } protected Book(Parcel in) { bookId = in.readInt(); bookName= in.readString(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(bookId); dest.writeString(bookName); } @Override public int describeContents() { return 0; } public static final Creator<Book> CREATOR = new Creator<Book>() { @Override public Book createFromParcel(Parcel in) { return new Book(in); } @Override public Book[] newArray(int size) { return new Book[size]; } }; @Override public String toString() { return "bookName = " +bookName + "bookId = " + bookId; } }
public class MainActivity extends AppCompatActivity { public static final String TAG ="XCR_MainActivity"; private TextView mTextView; private Context mContext; Intent intent; int i = 0; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG,"service name :" + service); IBookManager iBookManager = IBookManager.Stub.asInterface(service); try { // iBookManager.addBook(new Book(1,"ANDROID")); List<Book> books = iBookManager.getBookList(); Log.d(MainActivity.TAG,"books.size() =" + books.size()); iBookManager.registerNewBookArrivedListener(new IBookArrivedListener.Stub() { @Override public void onNewBookArrived(Book book) throws RemoteException { Log.d(MainActivity.TAG,"receive book info ,book = " + book.toString()); } }); } catch (RemoteException e) { Log.e(MainActivity.TAG,e.getMessage()); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(MainActivity.TAG,"main onCreate" + Thread.currentThread()); setContentView(R.layout.activity_main); mTextView =(TextView) findViewById(R.id.textView); mContext = this; mTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { i ++; intent = new Intent(mContext,MyService.class); mContext.bindService(intent,mServiceConnection,BIND_AUTO_CREATE); // mContext.startService(intent); if(i > 1){ mContext.unbindService(mServiceConnection); } } }); } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG,"ACTIVITY onDestroy"); // mContext.unbindService(mServiceConnection); mContext.stopService(intent); } }
public class MyService extends Service{ private CopyOnWriteArrayList<Book> mBooksList =new CopyOnWriteArrayList<>(); private IBookArrivedListener mIBookArrivedListener; private AtomicBoolean isUnbindService = new AtomicBoolean(false); private IBinder mIBinder = new IBookManager.Stub(){ @Override public List<Book> getBookList() throws RemoteException { return mBooksList; } @Override public void addBook(Book book) throws RemoteException { mBooksList.add(book); Log.d(MainActivity.TAG,"book.toString()= " + book.toString()); } @Override public void registerNewBookArrivedListener(IBookArrivedListener bookArrivedListenre) throws RemoteException { mIBookArrivedListener = bookArrivedListenre; } @Override public void unRegisterNewBookArrivedListener(IBookArrivedListener bookArrivedListenre) throws RemoteException { mIBookArrivedListener = null; } }; @Nullable @Override public IBinder onBind(Intent intent) { Log.d(MainActivity.TAG,"onBind"); Log.d(MainActivity.TAG,"service onBind" + Thread.currentThread()); return mIBinder; } @Override public void onCreate() { Log.d(MainActivity.TAG,"service onCreate" + Thread.currentThread()); Log.d("XCR_MainActivity","onCreate" ); new Thread(new Runnable() { @Override public void run() { int i = 0; while(!isUnbindService.get()){ i++; try { Thread.sleep(5000); } catch (InterruptedException e) { Log.e(MainActivity.TAG,e.getMessage()); } Book book = new Book(i,"android" + i); if(!mBooksList.contains(book)) { mBooksList.add(book); Log.d("XCR_MainActivity","mBooksList.size()= " +mBooksList.size()); try { if(null != mIBookArrivedListener) { mIBookArrivedListener.onNewBookArrived(book); } } catch (RemoteException e) { Log.e("XCR_MainActivity",e.getMessage()); } } } } }).start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(MainActivity.TAG,"onStartCommand" + Thread.currentThread()); return 3; } @Override public boolean onUnbind(Intent intent) { Log.d(MainActivity.TAG,"onUnbind" + Thread.currentThread()); Log.d(MainActivity.TAG,"onUnbind"); return true; } @Override public void onDestroy() { Log.d(MainActivity.TAG,"onDestroy" + Thread.currentThread()); super.onDestroy(); isUnbindService.set(true); Log.d(MainActivity.TAG,"SERVICE onDestroy"); } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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.example.administrator.myaidl.MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="30dp" android:text="Hello World!" android:id="@+id/textView" /> </RelativeLayout>
log如下:
07-08 23:15:11.205 2848-2848/com.example.administrator.myaidl D/XCR_MainActivity: main onCreateThread[main,5,main]
07-08 23:15:30.442 3043-3043/? D/XCR_MainActivity: service onCreateThread[main,5,main]
07-08 23:15:30.442 3043-3043/? D/XCR_MainActivity: onCreate
07-08 23:15:30.444 3043-3043/? D/XCR_MainActivity: onBind
07-08 23:15:30.444 3043-3043/? D/XCR_MainActivity: service onBindThread[main,5,main]
07-08 23:15:30.446 2848-2848/com.example.administrator.myaidl D/XCR_MainActivity: service name :android.os.BinderProxy@26932a95
07-08 23:15:30.458 2848-2848/com.example.administrator.myaidl D/XCR_MainActivity: books.size() =0
07-08 23:15:35.460 3043-3066/com.example.administrator.myaidl:remote D/XCR_MainActivity: mBooksList.size()= 1
07-08 23:15:35.461 2848-2869/com.example.administrator.myaidl D/XCR_MainActivity: receive book info ,book = bookName = android1bookId = 1
07-08 23:15:40.462 3043-3066/com.example.administrator.myaidl:remote D/XCR_MainActivity: mBooksList.size()= 2
07-08 23:15:40.463 2848-2870/com.example.administrator.myaidl D/XCR_MainActivity: receive book info ,book = bookName = android2bookId = 2
07-08 23:15:45.463 3043-3066/com.example.administrator.myaidl:remote D/XCR_MainActivity: mBooksList.size()= 3
07-08 23:15:45.464 2848-2869/com.example.administrator.myaidl D/XCR_MainActivity: receive book info ,book = bookName = android3bookId = 3
07-08 23:15:45.634 3043-3043/com.example.administrator.myaidl:remote D/XCR_MainActivity: onUnbindThread[main,5,main]
07-08 23:15:45.635 3043-3043/com.example.administrator.myaidl:remote D/XCR_MainActivity: onUnbind
07-08 23:15:45.636 3043-3043/com.example.administrator.myaidl:remote D/XCR_MainActivity: onDestroyThread[main,5,main]
07-08 23:15:45.636 3043-3043/com.example.administrator.myaidl:remote D/XCR_MainActivity: SERVICE onDestroy
07-08 23:15:50.466 3043-3066/com.example.administrator.myaidl:remote D/XCR_MainActivity: mBooksList.size()= 4
07-08 23:15:50.467 2848-2870/com.example.administrator.myaidl D/XCR_MainActivity: receive book info ,book = bookName = android4bookId = 4
07-08 23:15:55.871 2848-2848/com.example.administrator.myaidl D/XCR_MainActivity: ACTIVITY onDestroy