編輯:關於Android編程
在後台長期運行的沒有界面的組件。其他組件可以啟動Service讓他在後台運行,或者綁定Service與它進行交互,甚至實現進程間通信(IPC)。例如,可以讓服務在後台處理網絡交互,播放音樂,文件I/O,或者與ContentProvider交互。
...
...
開啟服務:
Intent service = new Intent(this,Service.class);
startService(service);
停止服務:
Intent service = new Intent(this,Service.class);
stopService(service);
綁定服務:
private boolean mIsBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
// 服務連接成功回調
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyService.MyBinder binder = (MyService.MyBinder) service;
}
// 服務失去連接回調
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Event(value = R.id.btn_bind_service)
private void onBindServiceClick(View view) {
bindService(getServiceIntent(), mConnection, Context.BIND_AUTO_CREATE);// 綁定時如果沒有創建Service則自動創建Service。
mIsBound = true;
}
解綁服務:
@Event(value = R.id.btn_unbind_service)
private void onUnbindServiceClick(View view) {
if (!mIsBound) {
ToastUtil.show("未綁定服務");
return;
}
try {
unbindService(mConnection);//注意:ServiceConnection要傳綁定時的ServiceConnection對象,否則會報錯。
} catch (Exception e) {
ToastUtil.show("解除綁定服務失敗");
e.printStackTrace();
}
mIsBound = false;
}
public class MyService extends Service {
// 服務創建
@Override
public void onCreate() {
super.onCreate();
}
// 每次startService都會調用;通過bindService方式啟動服務,該方法不會被調用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
// 服務銷毀
@Override
public void onDestroy() {
super.onDestroy();
}
// bindService時調用,返回一個IBinder對象,用於與Service交互,IBinder就是Service的代理
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
// unbindService時調用
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
startService:onCreate——>onStartCommand
stopService:onDestory
注意:服務只會被創建一次,如果服務已經創建,並且沒有銷毀,多次調用startService方法,只會執行onStartCommand方法。
bindService:onCreate——>onBind
unbindService:onUnbind——>onDestory
注意:
如果多次bindService,onBind方法只會在第一次綁定時被調用;同樣,多次startService,onCreate方法也只會在第一次創建時被調用; 服務只能被解綁一次,服務需要先綁定才能解除綁定,多次解綁會報錯。 通過bindService方式啟動的Service,在調用unbindService時就會自動銷毀。 服務只會停止一次,多次調用stopService()的方法無效,但不報錯。 每次調用startService()開啟服務都會執行onStartCommand()方法。由於系統框架在創建服務的時候會創建與之對應的上下文,直接new出來的服務對象是沒有上下文的,所以直接new服務對象調用其方法會報異常。
與Service之間交互都是通過其代理人(IBinder)來間接調用Service裡的方法的。
這樣設計主要出於安全考慮,有限的暴露出一些方法,而不是直接返回服務對象,因為服務對象裡可能有一些成員變量和方法不允許外界直接訪問,需要保護起來。
一般IBinder(代理人)也應該設計成私有的,因為是IBinder中的一些數據也需要保護起來,只需要暴露出一些指定的方法,那麼外界如何引用IBinder對象呢?通過接口引用代理人,在接口定義供外界調用的方法,讓IBinder類實現該接口。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMiBpZD0="bindservice與startservice">bindService與startService
bindService與startService的區別:
綁定服務:可以間接調用服務裡面的方法;如果綁定的Activity被銷毀了,服務也會跟著銷毀。 開啟服務:不可以調用服務裡面的方法;如果開啟服務的Activity銷毀,服務還可以長期的在後台運行。既要保證服務長期在後台運行,又想去調用服務裡面的方法。
步驟:
1. startService(),保證服務在後台長期的運行;
2. bindService(),獲取中間人(IBinder對象),間接的調用服務裡面的方法;
這時,解綁服務並不會導致服務銷毀,服務可長期在後台運行。
注意:如果服務已經被綁定,直接調用stopService()是停不掉的,必須先解除綁定服務再調stopService(),服務才會被銷毀。
@ContentView(value = R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
private boolean mIsBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
// 服務連接成功回調
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogUtil.d(name + " onServiceConnected");
PayService.PayBinder binder = (PayService.PayBinder) service;
binder.pay(100);
}
// 服務失去連接回調
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtil.d(name + " onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
x.view().inject(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//當Activity被銷毀時解綁服務,因為如果已經綁定服務不顯式解綁會報異常。
onUnbindServiceClick(null);
}
private Intent getServiceIntent() {
return new Intent(this, PayService.class);
}
// 啟動服務
@Event(value = R.id.btn_start_service)
private void onStartServiceClick(View view) {
startService(getServiceIntent());
}
// 綁定服務
@Event(value = R.id.btn_bind_service)
private void onBindServiceClick(View view) {
bindService(getServiceIntent(), mConnection, Context.BIND_AUTO_CREATE);// 綁定時如果沒有創建服務則自動創建Service。
mIsBound = true;
}
// 解綁服務
@Event(value = R.id.btn_unbind_service)
private void onUnbindServiceClick(View view) {
if (!mIsBound) {
ToastUtil.show("未綁定服務");
return;
}
try {
unbindService(mConnection);//注意:ServiceConnection要傳綁定時的ServiceConnection對象,否則會報錯。
} catch (Exception e) {
e.printStackTrace();
}
mIsBound = false;
}
// 停止服務
@Event(value = R.id.btn_stop_service)
private void onStopServiceClick(View view) {
stopService(getServiceIntent());
}
}
參考文檔:
https://developer.android.com/reference/android/app/Service.html
https://developer.android.com/guide/components/services.html
AIDL(Android Interface Definition Language)用於進程間通信接口的定義,是一種進程間通訊的規范 。
Service端:
1.New一個aidl文件在src目錄下
2.在aidl文件中定義Service中對外開放的接口
// IPayService.aidl
package linchaolong.android.aidldemo.service;
// Declare any non-default types here with import statements
/**
* AIDL Demo
*
* Created by linchaolong on 2016/4/22.
*/
interface IPayService {
void pay(int price);
void startTimer();
void stopTimer();
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*
* 翻譯:
*
* 展示一些可以在AIDL中用作參數和返回值的基本類型。
*
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
aidl語言中沒有權限修飾符,因為進程間通信接口權限肯定是public的。
3.aidl編寫完成後,make一下工程,在build目錄下就會生成該aidl文件對應的java文件,比如我這是IPayService.java。
4.在IPayService中有一個Stub靜態類,繼承了Binder和實現了IPayService接口,定義一個Binder類繼承IPayService.Stub並實現相關接口。
@Override
public IBinder onBind(Intent intent) {
if (mBinder == null) {
mBinder = new PayBinder();
}
return mBinder; // 其他應用綁定服務時返回binder對象
}
// Binder
public class PayBinder extends IPayService.Stub {
public void pay(int price) {
PayService.this.pay(price);
}
public void startTimer() {
PayService.this.startTimer();
}
public void stopTimer() throws RemoteException {
PayService.this.stopTimer();
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
// Does nothing
}
}
5.在AndroidManifest.xml配置Service
到這裡Service端就完成了,其他應用需要調用該Service只需要把aidl文件拷貝到自己工程的src目錄下(make一下),並綁定服務即可得到IBinder對象,通過IBinder對象可以實現與Service的交互。
調用示例:
在onServiceConnected回調裡,調用YourServiceInterface.Stub.asInterface(service)把IBinder對象轉換為YourServiceInterface類型。
private IPayService iPayService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 獲取遠程接口實例
iPayService = IPayService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "Service has unexpectedly disconnected");
iPayService = null;
}
};
綁定遠程服務並調用IPC方法
/**
* 判斷是否已經綁定遠程服務
*
* @return
*/
private boolean isBinded() {
return mIsBound && iPayService != null;
}
private Intent getServiceIntent() {
return new Intent("linchaolong.android.aidldemo.service.PayService");
}
// 綁定遠程服務
@Event(value = R.id.btn_bind_remote_service)
private void bindRemoteService(View view) {
if (isBinded()) {
showToast("已綁定遠程服務");
return;
}
bindService(getServiceIntent(), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
// 調用遠程服務方法
@Event(value = R.id.btn_call_service_pay)
private void callServicePay(View view) {
if (!isBinded()) {
showToast("未綁定遠程服務");
return;
}
try {
// 通過IBinder對象調用遠程服務中方法
iPayService.pay(100);
} catch (RemoteException e) {
e.printStackTrace();
}
}
1.概述回到正題,這次帶來的效果,是一個Android 的3D立體旋轉的效果。當然靈感的來源,來自早些時間微博上看到的效果圖。非常酷有木有!作為程序猿我當然要把它加入我的
從寫第一篇今日頭條高仿系列開始,到現在已經過去了1個多月了,其實大體都做好了,就是遲遲沒有放出來,因為我覺得,做這個東西也是有個過程的,我想把這個模仿中一步一步學習的過程
GreenDao是Android當中的高性能ORM框架。(其他的有OrmLite等) 同時GreenDao還有一個子項目為GreenDao Code
進程狀態轉換,同樣可用於線程的狀態轉移一、進程狀態進程的生命周期內,有5種狀態,分別為new, runnable, running, blocked, de