service—Android的四大組件之一。人稱“後臺服務”指其本身的運行並不依賴於用戶可視的UI界面 實際開發中我們經常需要service和activity之間可以相互傳遞數據維持程式的運行。 先瞭解Service的生命周期吧。 新建一個類繼Service: 新建以上類並繼承Service後只會 ...
service—Android的四大組件之一。人稱“後臺服務”指其本身的運行並不依賴於用戶可視的UI界面
實際開發中我們經常需要service和activity之間可以相互傳遞數據維持程式的運行。
先瞭解Service的生命周期吧。
新建一個類繼Service:
package com.example.myservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 服務類(需要在項目清單文件中註冊服務)
*
* @author lenovo
*
*/
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
/**
* 服務創建的時候調用
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
System.out.println("=========onCreate======");
}
/**
* 服務啟動的時候調用
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("=========onStartCommand======");
return super.onStartCommand(intent, flags, startId);
}
/**
* 服務銷毀的時候調用
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("=========onDestroy======");
super.onDestroy();
}
}
新建以上類並繼承Service後只會重寫onBind()方法,其他方法是我手動手寫,為了弄清楚Service的生命周期
MainActivity中(設置兩個按鈕用來開始和停止服務):
package com.example.myservicedemo.ui;
import com.example.myservicedemo.R;
import com.example.myservicedemo.service.MyService;
import com.example.myservicedemo.service.MyService.DownLoadBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_stop = (Button) findViewById(R.id.btn_stop);
btn_start.setOnClickListener(this);
btn_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = v.getId();
switch (id) {
/*
* 開啟服務點擊事件
*/
case R.id.btn_start:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
/*
* 停止服務點擊事件
*/
case R.id.btn_stop:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
切記android中的服務是需要在項目清單文件中註冊的(AndroidStudio可以自動,eclipse需要手動添加):
<service android:name="服務類坐所在的包名.MyService"></service>
此時運行程式,點擊開啟服務時候輸出是下圖:(我輸出多次onStartCommand()是因為我連續點擊了多次開啟服務按鈕)
上圖可以看出服務第一次開啟時先是調用了onCreate()方法和onStartCommand()方法,多次點擊開始服務時只調用了onStartCommand()方法
so:
onCreate()方法是服務創建的時候調用的~
onStartCommand()方法在每次啟動服務的時候都會調用~
onDestory()方法在停止服務時候會調用~
點擊停止服務後,輸出如圖:
啟動服務還有一種方式是bindService();
此時的MyService類要做改變:
package com.example.myservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 服務類(需要在項目清單文件中註冊服務)
*
* @author lenovo
*
*/
public class MyService extends Service {
private DownLoadBinder downLoadBinder=new DownLoadBinder();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("=====onBind=====");
return downLoadBinder;
}
/**
* 內部類繼承Binder
* @author lenovo
*
*/
public class DownLoadBinder extends Binder{
public void startDownLoad(){
System.out.println("=====startDownLoad()=====");
}
public void getProgress(){
System.out.println("=====getProgress()=====");
}
}
/**
* 服務創建的時候調用
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
System.out.println("=========onCreate======");
}
/**
* 服務啟動的時候調用
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("=========onStartCommand======");
return super.onStartCommand(intent, flags, startId);
}
/**
* 服務銷毀的時候調用
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("=========onDestroy======");
super.onDestroy();
}
}
以上的代碼和第一次相比,一是多了一個內部類DownLoadBinder繼承IBinder並且聲明瞭兩個方法,二是將onBind方法的返回值改為了DownLoadBinder類型的變數
activity bindService方法啟動服務時候一般是需要傳遞數據的,核心就在onBind()方法中,往下看
MainActivity中加兩個按鈕:綁定服務和取消綁定服務
package com.example.myservicedemo.ui;
import com.example.myservicedemo.R;
import com.example.myservicedemo.service.MyService;
import com.example.myservicedemo.service.MyService.DownLoadBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private MyService.DownLoadBinder downLoadBinder;
private MyService myService; //我們自己的service
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_stop = (Button) findViewById(R.id.btn_stop);
Button btn_bind = (Button) findViewById(R.id.btn_bind);
Button btn_unbind = (Button) findViewById(R.id.btn_unbind);
btn_start.setOnClickListener(this);
btn_stop.setOnClickListener(this);
btn_bind.setOnClickListener(this);
btn_unbind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = v.getId();
switch (id) {
/*
* 開啟服務點擊事件
*/
case R.id.btn_start:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
/*
* 停止服務點擊事件
*/
case R.id.btn_stop:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
/*
* 綁定服務點擊事件
*/
case R.id.btn_bind:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
/*
* 解除綁定服務點擊事件
*/
case R.id.btn_unbind:
unbindService(connection);
break;
default:
break;
}
}
private ServiceConnection connection=new ServiceConnection() {
/**
* 服務解除綁定時候調用
*/
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
/**
* 綁定服務的時候調用
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//myService=((DownLoadBinder) service).
downLoadBinder=(DownLoadBinder) service;
/*
* 調用DownLoadBinder的方法實現參數的傳遞
*/
downLoadBinder.startDownLoad();
downLoadBinder.getProgress();
}
};
}
運行後點擊綁定服務後輸出如下:
說明成功綁定了服務且傳遞了數據,點擊解除綁定服務時候ondestory()方法輸出
不過這種方法好像只能傳遞一次數據,,,,不爽,,,,比如後臺在實時更新東西,activity需要實時獲取呢???
查找資料大多是以下幾種方式:
1.使用介面回調方式,activity實現相應的介面,service通過介面進行回調,比較靈活
2.使用廣播
這篇博客主要介紹第一種方法,為什麼不介紹第二種???——不願意介紹,不喜歡。
使用介面回調方式的MyService和MainActivity代碼我是備註詳細之後才粘貼的,大家可以看註釋
MyService代碼:
package com.example.myservicedemo.service;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 服務類(需要在項目清單文件中註冊服務)
*
* @author lenovo
*
*/
public class MyService extends Service {
private DownLoadBinder downLoadBinder=new DownLoadBinder();
/**
* 回調
*/
private Callback callback;
/**
* Timer實時更新數據的
*/
private Timer mTimer=new Timer();
/**
*
*/
private int num;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("=====onBind=====");
return downLoadBinder;
}
/**
* 內部類繼承Binder
* @author lenovo
*
*/
public class DownLoadBinder extends Binder{
/**
* 聲明方法返回值是MyService本身
* @return
*/
public MyService getService() {
return MyService.this;
}
}
/**
* 服務創建的時候調用
*/
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
/*
* 執行Timer 2000毫秒後執行,5000毫秒執行一次
*/
mTimer.schedule(task, 0, 1000);
}
/**
* 提供介面回調方法
* @param callback
*/
public void setCallback(Callback callback) {
this.callback = callback;
}
/**
*
*/
TimerTask task = new TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
num++;
if(callback!=null){
/*
* 得到最新數據
*/
callback.getNum(num);
}
}
};
/**
* 回調介面
*
* @author lenovo
*
*/
public static interface Callback {
/**
* 得到實時更新的數據
*
* @return
*/
void getNum(int num);
}
/**
* 服務銷毀的時候調用
*/
@Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("=========onDestroy======");
/**
* 停止Timer
*/
mTimer.cancel();
super.onDestroy();
}
}
MainActivity代碼:
package com.example.myservicedemo.ui;
import com.example.myservicedemo.R;
import com.example.myservicedemo.service.MyService;
import com.example.myservicedemo.service.MyService.Callback;
import com.example.myservicedemo.service.MyService.DownLoadBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private MyService.DownLoadBinder downLoadBinder;
// private MyService myService; //我們自己的service
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_stop = (Button) findViewById(R.id.btn_stop);
Button btn_bind = (Button) findViewById(R.id.btn_bind);
Button btn_unbind = (Button) findViewById(R.id.btn_unbind);
btn_start.setOnClickListener(this);
btn_stop.setOnClickListener(this);
btn_bind.setOnClickListener(this);
btn_unbind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = v.getId();
switch (id) {
/*
* 開啟服務點擊事件
*/
case R.id.btn_start:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
/*
* 停止服務點擊事件
*/
case R.id.btn_stop:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
/*
* 綁定服務點擊事件
*/
case R.id.btn_bind:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
/*
* 解除綁定服務點擊事件
*/
case R.id.btn_unbind:
unbindService(connection);
break;
default:
break;
}
}
private ServiceConnection connection=new ServiceConnection() {
/**
* 服務解除綁定時候調用
*/
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
/**
* 綁定服務的時候調用
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
downLoadBinder = (DownLoadBinder) service;
MyService service2 = downLoadBinder.getService();
/**
* 實現回調,得到實時刷新的數據
*/
service2.setCallback(new Callback() {
@Override
public void getNum(int num) {
// TODO Auto-generated method stub
System.out.println("====num===="+num);
}
});
}
};
}
運行後的結果應該輸出如圖就對了(輸出隨service中num的數量而更新):
期間遇到的問題:
bindService後無效,MyService類中的onBind()方法沒有被調用
解決:這種情況下你的Activity應該是繼承了TabBarActivity,綁定服務的時候調用寫這種形式:
this.getApplicationContext().bindService(intent, mConnection, BIND_AUTO_CREATE);
最近幾天用到,總結一下,希望可以為大家帶來幫助,有錯誤還請大神指正。