android中Service使用詳解
來源:程序員人生 發(fā)布時(shí)間:2016-08-29 09:13:54 閱讀次數(shù):2526次
service用于長時(shí)間在后臺(tái)處理任務(wù),而不需要對用戶可見。
service有2種基本的啟動(dòng)方式:
startService():使用這類方式,來進(jìn)行單1的任務(wù),不需要返回結(jié)果給調(diào)用者
bindService():與上面的相反。
下面是1些關(guān)于服務(wù)的重要說明,非常值得詳細(xì)了解的:
繼承service,實(shí)現(xiàn)自己的service;
在manifest中聲明service,服務(wù)位于主線程,其實(shí)不會(huì)創(chuàng)建自己的子線程。
下面是1些重寫的方法:
onCreate();當(dāng)服務(wù)被創(chuàng)建時(shí)調(diào)用,只調(diào)用1次。
onStartCommand();它與startService()對應(yīng),當(dāng)服務(wù)啟動(dòng)后調(diào)用。如果你重寫了該方法,你就有責(zé)任自己去
當(dāng)任務(wù)結(jié)束以后,調(diào)用stopSelf()或stopService()來停止服務(wù)。如果你是綁定的服務(wù),就不需重新該方法了。
onBind();它與bindService()對應(yīng),通過返回IBinder,來與service交換。如果你其實(shí)不像綁定它,就直接返回null
onDestroy();當(dāng)服務(wù)不再被使用時(shí)需要燒毀時(shí)調(diào)用,你應(yīng)當(dāng)在這里用來停止線程,注銷監(jiān)聽器,廣播。
如果1個(gè)組件如activity使用的是 startService()來啟動(dòng)服務(wù)的話,就會(huì)觸發(fā) onStartCommand(),然后服務(wù)就會(huì)1直運(yùn)行,直到任務(wù)結(jié)束;服務(wù)的停止需要
手動(dòng)控制:在啟動(dòng)服務(wù)的組件中調(diào)用 stopService()或在服務(wù)本類中調(diào)用stopSelf()
如果1個(gè)組件使用的是bindService()來啟動(dòng)服務(wù)的話,該服務(wù)就會(huì)運(yùn)行,直到組件不束縛它。
在系統(tǒng)內(nèi)存很低的情況下,系統(tǒng)會(huì)強(qiáng)迫停止服務(wù),來恢復(fù)用于運(yùn)行activity;但是下面這些情況下的服務(wù)不容易被系統(tǒng)停止:服務(wù)與activity綁定或
服務(wù)位于前臺(tái)。但是如果服務(wù)最后還是被停止了,我們要重新啟用服務(wù)。
service的創(chuàng)建和使用,
也能夠使用IntentService,它是service子類,在處理后臺(tái)任務(wù)時(shí),不需要你自己開線程,可以直接在 onHandleIntent()中進(jìn)行任務(wù)。
<span style="font-size:14px;">1.<manifest ... >
...
<application ... >
<service android:name=".ExampleService"
android:exported="false"
/>
...
</application>
</manifest>
public class HelloIntentService extends IntentService {
A constructor is required, and must call the super IntentService(String)
constructor with a name for the worker thread.
public HelloIntentService() {
super("HelloIntentService");
}
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
}
}</span>
<span style="font-size:14px;">
</span>
使用intentservice,在任務(wù)結(jié)束后會(huì)自動(dòng)關(guān)閉服務(wù)。
2.使用startService()來啟動(dòng)服務(wù),1般在不需要交互的情況下使用這類方式,
在onStartCommand()中接受Intent ;
Intent intent = new Intent(this, HelloService.class);
startService(intent);
如果你的服務(wù)沒有經(jīng)過綁定,那末startService(intent)中的intent就是唯1的向service交互的方式;service中通過廣播來向外發(fā)布回調(diào)。如果屢次啟動(dòng)服務(wù),會(huì)致使onStartCommand()被屢次調(diào)用。
onStartCommand()必須返回1個(gè)整形值,描寫這當(dāng)系統(tǒng)殺掉服務(wù)時(shí),系統(tǒng)該如何繼續(xù)service
START_NOT_STICKY,殺掉后,不再重建
START_STICKY,殺掉后,自動(dòng)重啟,然后接收的intent=null
START_REDELIVER_INTENT,殺掉后,自動(dòng)重啟,然后接收的intent不為空;像文件下載
3.使用bindService()啟動(dòng);這類方式使用更加復(fù)雜,但也更加靈活。
當(dāng)你需要與服務(wù)交互的時(shí)候,可以采取這類方式;
必須重寫 onBind()方法返回IBinder,來與其他組件交換。在其他組件中獲得該IBinder對象
有1種client-server的感覺,可以有多個(gè)客戶端與server交換
客戶端組件,必須創(chuàng)建ServiceConnection,用來監(jiān)聽與service的連接;
可以有多個(gè)客戶端連接service,但是service的onBind只會(huì)履行1次,所以分發(fā)給其他客戶真?zhèn)€都是同1個(gè)IBinder對象
只有在多個(gè)客戶端都解綁了服務(wù)以后,服務(wù)才會(huì)被燒毀。
使用這類服務(wù)有個(gè)最重要的地方就是定義IBinder;
有3種方式:
a.直接繼承Binder,這也是1般app經(jīng)常使用的1種方式,適用于你的服務(wù)與你的app是處于同1個(gè)進(jìn)程中的。你的服務(wù)僅僅是為了
處理后臺(tái)任務(wù)。
b.使用Messenger,適用于需要跨進(jìn)程通訊且線程安全且非并發(fā),同1個(gè)時(shí)間只能接遭到1個(gè)要求,你可使用Messenger和Handler這2個(gè) 類來進(jìn)行service和client的交互。
服務(wù)端建立信使對象,通過通過onbind將服務(wù)端信使對象放在IBind中回調(diào)給客戶端,這模樣客戶端就能夠拿到服務(wù)端信使對象,使用服務(wù)端信使對象給服務(wù)端發(fā)信息了。
在客戶端連接上服務(wù)端后,可以建立客戶端信使對象,將客戶端信使對象以消息的情勢,發(fā)送給服務(wù)端,服務(wù)端拿到客戶端信使對象后可以給客戶端發(fā)消息。
這個(gè)是線程安全的。由于都是在同1個(gè)隊(duì)列里,在同1個(gè)線程里進(jìn)行的。它本身是基于AIDL構(gòu)建的。
c.使用AIDL,適用于需要跨進(jìn)程,且非線程安全,能夠同1時(shí)間處理多個(gè)要求的場合。
它的使用是創(chuàng)建1個(gè).aidl file文件,里面定義接口,然后android sdk tool使用它來生成1個(gè)抽象類,抽象類里實(shí)現(xiàn)各種接口方法。
注意:對大多數(shù)利用,我們都不應(yīng)當(dāng)使用AIDL來bindservice.由于這會(huì)使得結(jié)果更復(fù)雜。
首先我們看第1種方式;直接繼承Binder,
例如1個(gè)場景1個(gè)app是用來音樂播放,它關(guān)聯(lián)了1個(gè)activity。activity啟用服務(wù)來后臺(tái)播放音樂。
服務(wù)端:
<span style="font-size:14px;">public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
//Class used for the client Binder. Because we know this service always
//runs in the same process as its clients, we don't need to deal with IPC.
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//method for clients
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}</span>
客戶端:
<span style="font-size:14px;">public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
//** Called when a button is clicked (the button in the layout file attaches to
// * this method with the android:onClick attribute)
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
// Defines callbacks for service binding, passed to bindService()
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}</span>
接下來我們看第2種方式;使用Messenger,
如果您只需要在 Activity 可見時(shí)與服務(wù)交互,則應(yīng)在 onStart() 期間綁定,在 onStop() 期間取消綁定。
如果您希望 Activity 在后臺(tái)停止運(yùn)行狀態(tài)下仍可接收響應(yīng),則可在 onCreate() 期間綁定,在 onDestroy() 期間取消綁定。請注意,這意味著您的 Activity 在其全部運(yùn)行進(jìn)程中(乃至包括后臺(tái)運(yùn)行期間)都需要使用服務(wù),因此如果服務(wù)位于其他進(jìn)程內(nèi),那末當(dāng)您提高該進(jìn)程的權(quán)重時(shí),系統(tǒng)終止該進(jìn)程的可能性會(huì)增加
下面是個(gè)完全的例子;客戶端和服務(wù)端使用Messenger來通訊。
服務(wù)端:Server_Service
<span style="font-size:14px;">package com.example.administrator.service_messenger;
import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.Toast;
/**
* 在manifest清單文件中聲明service為另起新的進(jìn)程。
*/
public class Server_Service extends Service {
private Messenger clientMessenger;
/**
* 服務(wù)真?zhèn)€handler
*/
class ServerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Client.MSG_FROM_CLIENT:
String fromClient = msg.getData().getString("msgFromClient");
//收到來自客戶真?zhèn)€信息
Toast.makeText(getApplicationContext(), fromClient, Toast.LENGTH_SHORT).show();
//回復(fù)1下客戶端
Message msgFromServer = Message.obtain(null, Client.MSG_FROM_SERVER);
msgFromServer.arg1 =200;
try {
clientMessenger.send(msgFromServer);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case Client.MSG_FROM_CLIENT_MESSE: //得到客戶真?zhèn)€信使對象
clientMessenger = msg.replyTo;
break;
}
}
}
/**
* 服務(wù)真?zhèn)€Messenger,使用服務(wù)真?zhèn)€handler做參數(shù)構(gòu)造。
*/
final Messenger serverMessenger = new Messenger(new ServerHandler());
/**
* 我們在這里使用服務(wù)真?zhèn)€信使對象serverMessenger的IBinder,將其返回給客戶端中的
* serviceConntected
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "客戶端綁定服務(wù)端成功", Toast.LENGTH_SHORT).show();
return serverMessenger.getBinder();
}
@Override
public void unbindService(ServiceConnection conn) {
super.unbindService(conn);
Toast.makeText(getApplicationContext(), "客戶端取消了服務(wù)綁定", Toast.LENGTH_SHORT).show();
}
}
</span>
在manifest下配置:
<span style="font-size:14px;"><service android:name=".Server_Service"
android:process=":v1"/></span>
客戶端:Client
<span style="font-size:14px;">package com.example.administrator.service_messenger;
import android.content.ComponentName;
import android.content.Context;
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.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
public class Client extends AppCompatActivity {
public static final int MSG_FROM_CLIENT = 1;
public static final int MSG_FROM_CLIENT_MESSE = 2;
public static final int MSG_FROM_SERVER = 3;
//在客戶端里拿到了服務(wù)真?zhèn)€信使對象
Messenger serverMessenger = null;
//標(biāo)記是不是已連上了服務(wù)端
boolean mBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
//綁定服務(wù)
findViewById(R.id.bt_bind).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService();
}
});
//通過服務(wù)真?zhèn)€信使來發(fā)信息給服務(wù)端
findViewById(R.id.bt_send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendInfoToServer();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
//手動(dòng)解綁服務(wù)
findViewById(R.id.bt_unbind).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
unBindService();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//在activity燒毀時(shí),可以選擇取消綁定服務(wù)
unBindService();
}
//客戶真?zhèn)€handler
private Handler clientHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FROM_SERVER:
Toast.makeText(getApplicationContext(), "server received :"+msg.arg1+"", Toast.LENGTH_SHORT).show();
break;
}
}
};
/**
* 客戶真?zhèn)€Messenger,使用客戶的handler做參數(shù)構(gòu)造。
*/
final Messenger clientMessenger = new Messenger(clientHandler);
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
//當(dāng)我們連接上服務(wù)端后,會(huì)調(diào)用該方法。在方法里會(huì)回調(diào)給我們IBinder對象,
//由于bindservice綁定服務(wù)后,服務(wù)端返回給客戶真?zhèn)€IBinder是同1個(gè)。
//所以這里我們可以利用IBinder來構(gòu)建服務(wù)端里的信使對象。
//以后有了服務(wù)真?zhèn)€信使對象,就能夠隨意網(wǎng)服務(wù)端發(fā)送信息了。
//構(gòu)建服務(wù)端信使對象
serverMessenger = new Messenger(service);
mBound = true;
//并將客戶真?zhèn)€messenger發(fā)給服務(wù)端,讓服務(wù)端也能夠給客戶端發(fā)送消息
Message msg = Message.obtain(null, MSG_FROM_CLIENT_MESSE);
msg.replyTo = clientMessenger;
try {
serverMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
// 當(dāng)連接服務(wù)端異常時(shí)調(diào)用
serverMessenger = null;
mBound = false;
}
};
private void sendInfoToServer() throws UnsupportedEncodingException {
if (!mBound) return;
Message msg = Message.obtain(null, MSG_FROM_CLIENT, 0, 0);
String strMsg = "server received:" + Calendar.getInstance().getTime();
Bundle data = new Bundle();
data.putString("msgFromClient", strMsg);
msg.setData(data);
try {
serverMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onStart() {
super.onStart();
// 在界面可見時(shí),可以選擇去綁定服務(wù)
}
@Override
protected void onStop() {
super.onStop();
// 在界面不可見時(shí),可以選擇去解綁服務(wù)
}
private void bindService() {
bindService(new Intent(this, Server_Service.class), mConnection,
Context.BIND_AUTO_CREATE);
}
private void unBindService() {
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
</span>
最后我們來看第3種方式使用AIDL:
這類方式支持多個(gè)要求同時(shí)進(jìn)行,使用的時(shí)候要保證能夠并發(fā)。
基本流程:
與上面的使用信使1樣,只不過IBinder的獲得渠道不1樣罷了,這里是使用創(chuàng)建.aidl文件來實(shí)現(xiàn)。
最重要的點(diǎn):創(chuàng)建.aidl文件,里面定義1些接口,這些接口包括由服務(wù)端實(shí)現(xiàn)的,和客戶端實(shí)現(xiàn)的。
服務(wù)端實(shí)現(xiàn)的接口,就是由.aidl文件生成的接口文件,我們在服務(wù)端繼承該接口文件里定義的1個(gè)靜態(tài)內(nèi)部抽象類Stub,該類是Binder的子類,
正好可讓我們在OnBind方法中返回給客戶端。
如果你要服務(wù)端回調(diào)該客戶端信息,你要再定義1個(gè).aidl文件,里面包括回調(diào)方法。將該接口作為參數(shù),在上面1個(gè).aidl文件中定義注冊和反注冊方法;這樣,當(dāng)客戶端連接成功服務(wù)端后,讓客戶端實(shí)現(xiàn)該接口對象,作為實(shí)參傳遞進(jìn)來,最后就傳給了服務(wù)端。服務(wù)端拿著對象往客戶端發(fā)信息。
下面是1個(gè)例子:
例子結(jié)構(gòu)圖:
Book.java
package com.example.books.aidl;
import android.os.Parcel;
import android.os.Parcelable;
//Book要實(shí)現(xiàn)跨進(jìn)程,需要實(shí)現(xiàn)parcelable接口;還要定義該類的aidl文件
public class Book implements Parcelable {
public int bk_id;
public String name;
public double price;
public Book(int bk_id, String name, double price) {
super();
this.bk_id = bk_id;
this.name = name;
this.price = price;
}
public Book() {
super();
}
@Override
public String toString() {
return "Book [bk_id=" + bk_id + ", name=" + name + ", price=" + price
+ "]"+"\n";
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bk_id);
dest.writeString(name);
dest.writeDouble(price);
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel source) {
int bk_id = source.readInt();
String name = source.readString();
double price = source.readDouble();
return new Book(bk_id, name, price);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
}
Book.aidl
package com.example.books.aidl;
parcelable Book;
ICallBack.aidl
package com.example.books.aidl;
import com.example.books.aidl.Book;
//用于服務(wù)端回調(diào)給客戶端使用;在客戶端中定義,由服務(wù)端調(diào)用
interface ICallBack {
void success_GetBookList(in List<Book> allBook);
void success_AddBook(in Book book);
}
IBookManager.aidl
package com.example.books.aidl;
import com.example.books.aidl.Book;
import com.example.books.aidl.ICallBack;
//服務(wù)端返回給客戶端遠(yuǎn)程接口
interface IBookManager {
//客戶端調(diào)用
void requestGetBookList(); // 返回書籍列表
void requestAddBook(in Book book); // 添加書籍
//監(jiān)聽客戶端行動(dòng),在連接服務(wù)成功后,注冊客戶端監(jiān)聽
void registerListener(ICallBack listener); // 注冊接口
void unregisterListener(ICallBack listener); // 注冊接口
}
BookManagerService.java
package com.example.books.service;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import com.example.books.aidl.Book;
import com.example.books.aidl.IBookManager;
import com.example.books.aidl.ICallBack;
public class BookManagerService extends Service {
protected static final String TAG = "book";
// 支持并發(fā)讀寫
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
// 客戶端數(shù)量
private RemoteCallbackList<ICallBack> mListenerList = new RemoteCallbackList<>();
private ExecutorService cacheExecutorService = Executors
.newCachedThreadPool();
// 返回給客戶真?zhèn)€接口對象;客戶端調(diào)用
private Binder mBinder = new IBookManager.Stub() {
@Override
public void registerListener(ICallBack listener) throws RemoteException {
mListenerList.register(listener);
int num = mListenerList.beginBroadcast();
mListenerList.finishBroadcast();
Log.e(TAG, "添加完成, 注冊接口數(shù): " + num);
}
@Override
public void unregisterListener(ICallBack listener)
throws RemoteException {
mListenerList.unregister(listener);
int num = mListenerList.beginBroadcast();
mListenerList.finishBroadcast();
Log.e(TAG, "刪除完成, 注冊接口數(shù): " + num);
}
//多線程處理,可以在同1時(shí)間同時(shí)進(jìn)行多個(gè)要求。
@Override
public void requestGetBookList() throws RemoteException {
cacheExecutorService.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mListenerList.beginBroadcast();
ICallBack listener = mListenerList.getBroadcastItem(0);
Log.e(TAG, "發(fā)送通知: " + listener.toString());
try {
listener.success_GetBookList(mBookList);
} catch (RemoteException e) {
e.printStackTrace();
}
mListenerList.finishBroadcast();
}
});
}
//多線程處理
@Override
public void requestAddBook(final Book book) throws RemoteException {
cacheExecutorService.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mBookList.add(book);
mListenerList.beginBroadcast();
ICallBack listener = mListenerList.getBroadcastItem(0);
Log.e(TAG, "發(fā)送通知: " + listener.toString());
try {
listener.success_AddBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
mListenerList.finishBroadcast();
}
});
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
MainActivity.java
package com.example.books;
import java.util.List;
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.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.example.books.aidl.Book;
import com.example.books.aidl.IBookManager;
import com.example.books.aidl.ICallBack;
import com.example.books.service.BookManagerService;
public class MainActivity extends Activity implements OnClickListener {
private TextView tv_list;
private IBookManager mRemoteBookManager;
// 服務(wù)端給客戶真?zhèn)€回調(diào)
private ICallBack callBack = new ICallBack.Stub() {
@Override
public void success_GetBookList(final List<Book> allBook)
throws RemoteException {
runOnUiThread(new Runnable() {
public void run() {
tv_list.setText(allBook.toString());
}
});
}
@Override
public void success_AddBook(final Book book) throws RemoteException {
runOnUiThread(new Runnable() {
public void run() {
toast("成功添加書本:" + book);
}
});
}
};
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
isConnected = true;
mRemoteBookManager = IBookManager.Stub.asInterface(service);
toast("connected success");
// 監(jiān)聽將數(shù)據(jù)回調(diào)給客戶端
try {
mRemoteBookManager.registerListener(callBack);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteBookManager = null;
isConnected = false;
}
};
private EditText et_id;
private EditText et_name;
private EditText et_price;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_list = (TextView) findViewById(R.id.tv_list);
findViewById(R.id.bt_bind).setOnClickListener(this);
findViewById(R.id.bt_getAll).setOnClickListener(this);
findViewById(R.id.bt_add).setOnClickListener(this);
et_id = (EditText) findViewById(R.id.et_id);
et_name = (EditText) findViewById(R.id.et_name);
et_price = (EditText) findViewById(R.id.et_price);
}
@Override
protected void onDestroy() {
if (isConnected == true) {
isConnected = false;
try {
mRemoteBookManager.unregisterListener(callBack);
unbindService(mConnection);
} catch (Exception e) {
e.printStackTrace();
}
}
super.onDestroy();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_bind:
startBindService();
break;
case R.id.bt_add:
if (isConnected == false) {
return;
}
String id = et_id.getText().toString();
String name = et_name.getText().toString();
String price = et_price.getText().toString();
Book book = new Book(Integer.valueOf(id), name,
Double.valueOf(price));
try {
mRemoteBookManager.requestAddBook(book);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.bt_getAll:
if (isConnected == false) {
return;
}
try {
mRemoteBookManager.requestGetBookList();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
private boolean isConnected = false;
private void startBindService() {
if (isConnected == false) {
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
} else {
toast("has Connected");
}
}
private void toast(String msg) {
Toast.makeText(getApplicationContext(), msg, 0).show();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf⑻"?>
<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:orientation="vertical" >
<Button
android:id="@+id/bt_bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="bindService"
android:text="綁定服務(wù)" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="@+id/et_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="1" />
<EditText
android:id="@+id/et_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="紅馬" />
<EditText
android:id="@+id/et_price"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:inputType="number"
android:text="32" />
</LinearLayout>
<Button
android:id="@+id/bt_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加1本圖書" />
<Button
android:id="@+id/bt_getAll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="獲得所有圖書" />
<TextView
android:id="@+id/tv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getBookList"
android:text="顯示圖書列表" />
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf⑻"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.books"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<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="com.example.books.service.BookManagerService"
android:process=":remote_v1" >
</service>
</application>
</manifest>
效果圖:

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)