如何給Android應用創建本地服務


Android系統給應用提供了兩種類型的服務:啟動型本地服務和綁定型本地服務,這兩種服務的詳細信息請參考“Android Service開發指南”

Android Service開發指南原文網址如下:

http://developer.android.com/guide/topics/fundamentals/services.html

http://developer.android.com/guide/topics/fundamentals/bound-services.html

本文通過代碼向大家詳細介紹和演示這兩種的服務的創建過程,代碼適用於Android2.3.3以后的版本。

1. 定義清單文件(AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<!-- 本例為了方便,將啟動類型服務的Activity和綁定類型服務的Activity放到了一個類中:

     LocalServiceActivities.java -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="my.android.test"

      android:versionCode="1"

      android:versionName="1.0">

    <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="9"/>

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <!-- 本地服務LocalService -->

        <service android:name="LocalService" />

        <!-- 啟動類型服務的Activity,內部類Controller-->

        <activity android:name=".LocalServiceActivities$Controller"

                  android:label="@string/app_name"

                  android:launchMode="singleTop">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

         <!-- 綁定類型服務的Activity,要運行本服務,需要將下面的注釋去掉,

                                    同時給上面的啟動類型服務的Activity給注釋掉 -->

         <!--

        <activity android:name=".LocalServiceActivities$Binding"

                  android:label="@string/app_name"

                  android:launchMode="singleTop">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

          -->

    </application>

</manifest>

2. 定義字符資源(strings.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <string name="hello">Hello World, LocalServiceActivity!</string>

    <string name="app_name">LocalServiceApp</string>

    <string name="activity_local_service_controller">App/Service/Local Service Controller</string>

    <string name="local_service_controller">This demonstrates how you can implement persistent services that

        may be started and stopped as desired.</string>

    <string name="start_service">Start Service</string>

    <string name="stop_service">Stop Service</string>

   

    <string name="local_service_started">Local service has started</string>

    <string name="local_service_stopped">Local service has stopped</string>

    <string name="local_service_label">Sample Local Service</string>

   

    <string name="activity_local_service_binding">App/Service/Local Service Binding</string>

    <string name="local_service_binding">This demonstrates how you can connect with a persistent

        service.  Notice how it automatically starts for you, and play around with the

        interaction between this and Local Service Controller.</string>

    <string name="bind_service">Bind Service</string>

    <string name="unbind_service">Unbind Service</string>

    <string name="local_service_connected">Connected to local service</string>

    <string name="local_service_disconnected">Disconnected from local service</string>

</resources>

3. 定義布局資源

3.1. local_service_controller.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"

    android:gravity="center_horizontal"

    android:layout_width="match_parent" android:layout_height="match_parent">

    <TextView

        android:layout_width="match_parent" android:layout_height="wrap_content"

        android:layout_weight="0"

        android:paddingBottom="4dip"

        android:text="@string/local_service_controller"/>

    <Button android:id="@+id/start"

        android:layout_width="wrap_content" android:layout_height="wrap_content"

        android:text="@string/start_service">

        <requestFocus />

    </Button>

    <Button android:id="@+id/stop"

        android:layout_width="wrap_content" android:layout_height="wrap_content"

        android:text="@string/stop_service">

    </Button>

</LinearLayout>

3.2. local_service.binding.xml

    <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"

    android:gravity="center_horizontal"

    android:layout_width="match_parent" android:layout_height="match_parent">

    <TextView

        android:layout_width="match_parent" android:layout_height="wrap_content"

        android:layout_weight="0"

        android:paddingBottom="4dip"

        android:text="@string/local_service_binding"/>

    <Button android:id="@+id/bind"

        android:layout_width="wrap_content" android:layout_height="wrap_content"

        android:text="@string/bind_service">

        <requestFocus />

    </Button>

    <Button android:id="@+id/unbind"

        android:layout_width="wrap_content" android:layout_height="wrap_content"

        android:text="@string/unbind_service">

    </Button>

</LinearLayout>

4.  創建服務啟動界面(LocalServiceActivities.java

package my.android.test;

 

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.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

/**

 * 該類中包含兩種類型服務的客戶端:

 * 啟動類型服務客戶端:Controller

 * 綁定類型服務客戶端:Binding

 */

publicclass LocalServiceActivities {

    /**

     * Controller類是啟動類型服務的客戶端,它包含兩個按鈕:

     * start:點擊該按鈕時,啟動服務。

     * stop: 點擊該按鈕時,終止服務。

     */

    publicstaticclass Controller extends Activity{

       /**

        * Activity被首次啟動時,調用該方法。

        */

       @Override

       protectedvoid onCreate(Bundle savedInstanceState){

           super.onCreate(savedInstanceState);

           //填充布局

           setContentView(R.layout.local_service_controller);

           //查找布局中的啟動服務按鈕,並設置點擊事件監聽器。

           Button button = (Button)findViewById(R.id.start);

           button.setOnClickListener(mStartListener);

           //查找布局中的終止服務按鈕,並設置點擊事件監聽器。

           button = (Button)findViewById(R.id.stop);

           button.setOnClickListener(mStopListener);

       }

       /**

        * start按鈕的點擊事件監聽器實現。

        */

       private OnClickListener mStartListener = new OnClickListener(){

           publicvoid onClick(View v){

              //啟動LocalService服務。

              startService(new Intent(Controller.this, LocalService.class));

           }

       };

       /**

        * stop按鈕的點擊事件監聽器實現。

        */

       private OnClickListener mStopListener = new OnClickListener(){

           publicvoid onClick(View v){

              //終止LocalService服務。

              stopService(new Intent(Controller.this, LocalService.class));

           }

       };

    }

   

    /***************************************************************

     *以下是綁定型服務客戶端的實現

     ***************************************************************/

   

    /**

     * Binding類是綁定類型服務的客戶端,它包含兩個按鈕:

     * bind:點擊該按鈕時,調用bindService()方法綁定並啟動服務;

     * unbind:點擊該按鈕時,調用unbindService()方法解除綁定並終止服務。

     */

    publicstaticclass Binding extends Activity{

       //用於保存服務的綁定狀態,true:綁定,false:未綁定

       privatebooleanmIsBound;

       //用於保存被綁定的本地服務實例。

       private LocalService mBoundService;

       /**

        * 實現監視被綁定服務狀態的接口:ServiceConnection

        * 綁定類型服務都要實現這個接口,以便監視服務的狀態,這個接口中的方法會在

        * 應用的主線程中被調用。

        */

       private ServiceConnection mConnection = new ServiceConnection(){

           /**

            * 當連接的服務被創建時,Android系統會調用這個方法,用IBinder對象跟服務建立通信通道。

            * @param className:被連接的具體的服務組件的名稱

            * @param service:服務的通信通道IBinder對象。

            */

           publicvoid onServiceConnected(ComponentName className, IBinder service){

              //IBinder對象中獲取服務實例。

              mBoundService = ((LocalService.LocalBinder)service).getService();

              //顯示Activity已經與服務建立了連接的提示消息。

              Toast.makeText(Binding.this, R.string.local_service_connected, Toast.LENGTH_SHORT).show();

             

           }

           /**

            * 當服務被終止時,Android系統會調用這個方法。

            */

           publicvoid onServiceDisconnected(ComponentName className){

              //清除客戶端服務實例

              mBoundService = null;

              //顯示服務被終止的提示消息。

              Toast.makeText(Binding.this, R.string.local_service_disconnected, Toast.LENGTH_SHORT).show();

           }

       };

      

       /**

        * 綁定並啟動服務,bind按鈕點擊時會調用這個方法。

        */

       void doBindService(){

           //綁定並啟動服務。

           bindService(new Intent(Binding.this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);

           mIsBound = true;

       }

      

       /**

        * 解除與服務的綁定,unbind按鈕被點擊時會調用這個方法

        */

       void doUnbindService(){

           //如果服務被綁定,則解除與服務綁定。

           if(mIsBound){

              unbindService(mConnection);

              mIsBound = false;

           }

       }

      

       /**

        * Activity被銷毀時,調用解除綁定服務的方法,解除被綁定的服務。

        */

       @Override

       protectedvoid onDestroy(){

           super.onDestroy();

           //解除被綁定的服務。

           doUnbindService();

       }

      

       /**

        * bind按鈕的點擊事件監聽器接口實現。

        */

       private OnClickListener mBindListener = new OnClickListener(){

           publicvoid onClick(View v){

              //綁定並啟動服務。

              doBindService();

           }

       };

       /**

        * unbind按鈕的點擊事件監聽器接口實現。

        */

       private OnClickListener mUnbindListener = new OnClickListener(){

           publicvoid onClick(View v){

              //解除被綁定的服務。

              doUnbindService();

           }

       };

       /**

        * Activity被首次啟動時,會調用這個方法。

        */

       @Override

       protectedvoid onCreate(Bundle savedInstanceState){

           super.onCreate(savedInstanceState);

           //填充Activity

           setContentView(R.layout.local_service_binding);

           //查找布局中的bind按鈕,並設置點擊事件的監聽器

           Button button = (Button)findViewById(R.id.bind);

           button.setOnClickListener(mBindListener);

           //查找布局中的unbind按鈕,並設置點擊事件的監聽器

           button = (Button)findViewById(R.id.unbind);

           button.setOnClickListener(mUnbindListener);

       }

    }

}

5. 創建服務(LocalService.java

package my.android.test;

 

import android.app.Service;

import android.content.Intent;

import android.os.Binder;

import android.os.HandlerThread;

import android.os.IBinder;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.os.Process;

import android.util.Log;

import android.widget.Toast;

 

/**

 * LocalService基礎AndroidService類,實現應用的本地服務組件。

 * 該服務使用HandlerThread類創建了服務自己的線程和消息循環,

 * 因此,不會因為服務中的長時處理,而阻塞界面的刷新,影響用戶體驗。

 */

publicclass LocalService extends Service {

    //用於保存本服務自己的消息循環對象Looper

    private Looper mServiceLooper;

    //用於保存內部類ServiceHandler的對象實例,它繼承了AndroidHandler,

    //用於處理發送給服務的消息。

    private ServiceHandler mServiceHandler;

   

    /**

     * 這個類用於給客戶端提供綁定對象,因為本示例的服務與客戶端運行在同一個

     * 主進程中,所以不需要處理進程間通信(IPC

     */

    publicclass LocalBinder extends Binder{

       LocalService getService(){

           //返回本服務的實例。

           return LocalService.this;

       }

    }

    /**

     * 服務被首次創建時,系統調用這個方法。

     * Android服務組件必須覆寫這個方法

     */

    @Override

    publicvoid onCreate(){

       //創建線程對象,並啟動線程。

       HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);

       thread.start();

       //獲取線程的消息循環對象

       mServiceLooper = thread.getLooper();

       //用線程的消息循環對象創建消息處理對象。

       mServiceHandler = new ServiceHandler(mServiceLooper);

    }

   

    /**

     * 啟動類型服務必須實現這個方法,客戶端每次調用startService()方法時,

     * 系統都會調用這個方法。

     * @param intent:它是傳遞給startService()方法的Intent對象。

     * @param flags:有關啟動請求的附加數據,可以是:0START_FLAG_REDELIVERYSTART_FLAG_RETRY.

     * @param startId:一個唯一的整數,代表一次具體的請求,用於stopSelfResult(int)方法。

     */

    @Override

    publicint onStartCommand(Intent intent, int flags, int startId){

       Log.i("LocalService", "Received star id" + startId + ":" + intent);

       //顯示服務啟動的提示信息

       Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

       //獲取要傳遞給服務消息循環的Message對象。

       Message msg = mServiceHandler.obtainMessage();

       //初始化Message對象的成員變量。

       msg.arg1 = startId;

       msg.obj = "Message processing......" + startId;

       //把消息發送給服務線程的消息循環。

       mServiceHandler.sendMessage(msg);

       returnSTART_STICKY;

    }

   

    /**

     * 必須覆寫這個方法,服務被終止時要調用這個方法,清理服務所占用的資源。

     */

    @Override

    publicvoid onDestroy(){

       //退出服務線程的消息循環。

       mServiceLooper.quit();

       //顯示服務被退出的提示信息。

       Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();

    }

   

    /**

     * 綁定型服務必須覆寫這個方法,啟動型服務也可覆寫這個方法,只要返回null即可。

     */

    @Override

    public IBinder onBind(Intent intent){

       //返回本服務對象實例。

       returnmBinder;

    }

    privatefinal IBinder mBinder = new LocalBinder();

    /**

     * 該類繼承AndroidHandler類,為線程的消息循環提供發送和處理消息的功能,

     * 本示例覆寫了handleMessage()方法,用來處理發送給服務消息循環的消息。

     */

    privatefinalclass ServiceHandler extends Handler{

       //類實例化時,需要傳入服務線程的消息循環對象

       public ServiceHandler(Looper looper){

           super(looper);

       }

       /**

        * 覆寫Handler類的handleMessage()方法,當服務線程的消息循環接收到外部

        * 發送的消息時,會調用這個方法來處理對應的消息,本示例只是簡單的向用戶提示消息被處理的信息。

        */

       @Override

       publicvoid handleMessage(Message msg){

           long endTime = System.currentTimeMillis() + 5 * 1000;

           while (System.currentTimeMillis() < endTime){

              synchronized(this){

                  try{

                     wait(endTime - System.currentTimeMillis());

                     CharSequence  cs = msg.obj.toString();

                     Toast.makeText(LocalService.this, cs, Toast.LENGTH_SHORT).show();

                     //showNotification();

                  }catch(Exception e){

                     //

                  }

              }

           }

           //消息被處理之后,終止本服務。

           LocalService.this.stopSelf();

       }

    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM