Service我覺的跟Activity差不多,就是沒有界面。它是在後臺運行的。服務有自己的生命週期。接下來就學習以下內容:
想仔細瞭解的可以去官網學習
https://developer.android.com/guide/components/services.html
- 開啓服務生命週期和綁定服務生命週期
- 調用本地服務方法和遠程服務方法
開啓服務生命週期
佈局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.edu.androidforservicesimple.MainActivity">
<Button
android:onClick="start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="開啓服務"
/>
<Button
android:onClick="stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="關閉服務"
/>
</LinearLayout>
就兩個按鈕,很簡單
MyService.java代碼如下:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private static final String TAG="TAG";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate: ........");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ...........");
return super.onStartCommand(intent, flags, startId);
}
/**
* 已過時的方法
* @param intent
* @param startId
*/
@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "onStart: .........");
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ..............");
super.onDestroy();
}
}
MainActivity.java代碼如下:
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(MainActivity.this, MyService.class);
}
public void start(View view) {
startService(intent);
}
public void stop(View view) {
stopService(intent);
}
}
運行結果分析:
點擊開啓按鈕:執行的方法是:
點擊關閉按鈕:執行的方法是:
如果是點擊返回鍵時 ,不會關閉,它會一直運行在後臺
直到有調用 stopService(Intent i )方法,服務纔會關閉。還要補充的是:當又一次開啓服務時。onCreate()不會執行,它只會執行一次。只會執行onStartCommand()方法,
綁定服務生命週期
首先在MyService服務中添加兩個生命週期方法:
onUnbind()和onRebind()
然後改寫MainActivity.java 代碼如下:
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TAG";
private Intent intent;
ServiceConnection myConn = new ServiceConnection() {
//當服務被綁定時調用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected:.... ");
}
//當服務被解綁是調用
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: ...........");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(MainActivity.this, MyService.class);
}
public void start(View view) {
bindService(intent, myConn, BIND_AUTO_CREATE);
}
public void stop(View view) {
unbindService(myConn);
}
}
運行結果分析:
點擊開啓服務按鈕: 執行的方法是
再點擊開啓按鈕時: 不執行任何方法
當點擊關閉服務按鈕時 : 執行的方法是
如果點擊關閉服務按鈕後,再點擊開啓按鈕時又會執行onCreate和onBind這兩種方法。當按下返回鍵時,也會執行onUnbind和onDestroy方法。這個可以說明綁定服務時,它的生命週期跟啓動它服務的Activity活動的生命週期一樣。
我們先看下官網介紹這兩種方式的區別:
這張圖已經說明的很明顯了。講完這兩種方式的生命週期,我們該學習怎麼樣調用服務裏的方法。一種時是調用本地的,還一種是遠程調用的
調用本地服務的方法
activity_main.xml代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.edu.androidforinvokeservicemethod.MainActivity">
<Button
android:text="綁定服務"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="bind"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="unbind"
android:text="解除綁定"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="invoke"
android:text="調用服務中的方法"
/>
</LinearLayout>
MyService代碼如下 :
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
public MyService() {
}
public class MyBinder extends Binder {
public void getName() {
getMethodInService();
}
}
public void getMethodInService() {
Log.i("TAG", "我是來自服務中的方法");
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
}
MainActivity.java代碼如下:
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private Intent intent;
private MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(MainActivity.this, MyService.class);
}
ServiceConnection myConn = new ServiceConnection() {
//綁定服務時調用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
}
//解除綁定時調用
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
/**
* 綁定服務
*
* @param view
*/
public void bind(View view) {
bindService(intent, myConn, BIND_AUTO_CREATE);
}
/**
* 解綁服務
*
* @param view
*/
public void unbind(View view) {
unbindService(myConn);
}
/**
* 調用服務中的方法
*
* @param view
*/
public void invoke(View view) {
myBinder.getName();
}
}
先點擊綁定按鈕,再點擊調用按鈕
運行結果:
最後提一下,估計有人想new 一個服務實例來調用服務中的方法,其實這根本不行。因爲這是系統爲我們創建的。
接下來就重點學習怎麼調用遠程服務中的方法
首先創建個遠程服務端
創建個adil文件 在main目錄下:
代碼如下:
interface Person {
void getName();
}
就是聲明瞭一個方法,補充下,該方法不能有修飾符
在rebuild下該項目,會出現person接口
接下來就編寫MyService.java 代碼如下:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
public MyService() {
}
public class MyBinder extends Person.Stub {
@Override
public void getName() throws RemoteException {
getMethodInService();
}
}
public void getMethodInService(){
Log.i("TAG", " 我是來自遠程服務中的方法。。。。 ");
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
}
接下來我們再創建個Moudle,創建之前我們先把遠程服務的清單文件改下,設置下動作。因爲我們要通過這個來開啓遠程服務
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="edu.jju.remote"></action>
</intent-filter>
</service>
創建好了新的Moudle 就把遠程服務下定義的adil文件直接複製過來,帶包一起復制。然後複製到新創建的Moudle Main目錄下
複製完然後就rebuild下
activity_main.xml代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.edu.androidforinvokeremoteservice.MainActivity">
<Button
android:onClick="bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="綁定遠程服務"
/>
<Button
android:onClick="invoke"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="調用遠程服務中的方法"
/>
</LinearLayout>
就是兩個按鈕,簡單。哈哈
MainActivity.java代碼如下:
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.example.edu.androidforremoteservice.Person;
public class MainActivity extends AppCompatActivity {
private Intent intent;
private Person person;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent();
intent.setAction("edu.jju.remote");//該動作是遠程服務當中的
}
ServiceConnection myConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
person = Person.Stub.asInterface(service);//這個跟調用本地服務方法有些區別
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
/**
* 綁定遠程服務
* @param view
*/
public void bind(View view) {
bindService(intent, myConn, BIND_AUTO_CREATE);
}
/**
* 調用遠程服務中的方法
* @param view
* @throws RemoteException
*/
public void invoke(View view) throws RemoteException {
person.getName();
}
}
然後就是怎麼測試了。應該先運行遠程服務後,再執行這個調用遠程服務的項目
點擊綁定遠程服務按鈕,然後點擊調用遠程服務方法按鈕。
運行結果:
我居然一次就運行成功了,沒出問題。太佩服自己了。。哈哈
我已經把service服務講的差不多了,如果更詳細的瞭解服務的話可以去官網看。你也可以把我上面寫的跟着做一遍也差不多瞭解服務的基本知識了。基本上代碼全部在上面。
總結:
服務的啓動方式有兩種,一種是啓動另一種是綁定。綁定這種的生命週期跟綁定它的Activity生命週期一樣。再接下來我們就學習怎麼調用服務中的方法,也是兩種情況,1 調用本地服務中的方法,2 調用遠程服務中的方法。它們核心思想也是向外暴露接口,我感覺差不多。哈哈。。