【筆記】Service的使用

一、創建Service

  1.創建一個myService類,來繼承Service。重寫其中的方法,包括:onCreate(),onStartCommend(),onDestroy(),onBind()方法是自動重載的。

    1.1 onCreate():創建Service的時候調用,只調用一次。

    1.2 onStartCommend():執行Service的時候調用,執行幾次,調用幾次。

    1.3 onDestroy():在銷燬Service的時候調用,只調用一次。

    1.4 onBind():在bindService的時候調用。只調用一次。

  1.2 myService代碼如下:

複製代碼
package com.wangpei.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

/**
 * 作者:WangPei on 2015/7/9 09:48
 * 郵箱:[email protected]
 */
public class myService extends Service {

    private static final String TAG = "myInfo";
  //需要返回Binder實例
    private MyBinder myBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    @Override
    public void onCreate() {
        Log.i(TAG,"onCreate is excute");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"onStartCommand is excute");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG,"onDestroy is excute");
        super.onDestroy();
    }

    class  MyBinder extends Binder{

        public void startDownload(){
        //模擬下載任務
            Log.i(TAG,"startDownload is excute");
        }
    }
}
複製代碼

 

二、startService AND stopService

  2.1 startService

    2.1.1 代碼如下:

1
2
Intent startIntent = new Intent(MainActivity.this,myService.class);
                startService(startIntent);

    2.1.2 調用myService類中的方法順序如下:

        onCreate() ---> onStartCommend() ---先創建Service,然後在執行。

  2.2 stopService 代碼如下:

    2.2.1 代碼如下:

Intent stopIntent = new Intent(MainActivity.this,myService.class);
                stopService(stopIntent);

    2.2.2 調用myService類中的方法順序如下:

        onDestroy() --直接被銷燬。

三、bindService AND unBindService

  3.1 創建ServiceConnection:

複製代碼
//初始化myService中的binder
private myService.MyBinder myBinder;


private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (myService.MyBinder) service;
       //啓動下載任務
            myBinder.startDownload();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
複製代碼

    3.1.1 onServiceConnected()方法,是在Activity和Service建立連接的時候,進行調用。

    3.1.1 onServiceDisconnected()方法,onServiceDisconnected()方法不是解除關聯的時候調用,而是發生異常時調用的。

  3.2 bindService 代碼如下:

Intent bindIntent = new Intent(MainActivity.this,myService.class);
                bindService(bindIntent,connection,BIND_AUTO_CREATE);

    3.2.1 BIND_AUTO_CREATE:意思是在綁定Service的時候,進行自動創建。

  3.3 unBindService 代碼如下:

unbindService(connection);

  3.4 注意 如果同時startService和bindService,必須要stopService和unBindService,才能onDestroy()該Service。

   3.5 額外的東西

    樓主文中是有說明Service和Activity是如何通信的;首先在自定義的Service類中覆蓋onBind(Intent intent)方法,返回一個Binder子類的對象,在自定義的Binder子類中可以定義一些方法;然後再Activity創建個ServiceConnection對象,並實現其onServiceConnected(ComponentName name, IBinder service) 方法,在這個方法中將傳入的IBinder對象強轉爲在Service中定義的Binder子類,這樣就拿到了Service中的某個對象的引用了,想怎通信都行;但要使onServiceConnected方法被回調,還需要調用bindService方法,把ServiceConnection的對象當作參數傳過去......

四、Service AND Thread 的關係

  4.1 Service

    4.1.1 Service旨在後臺運行,並且Service也是在主線程中運行的。

    4.1.2 Service就不同了,所有的Activity都可以與Service進行關聯,然後可以很方便地操作其中的方法,即使Activity被銷燬了,之後只要重新與Service建立關聯,就又能夠獲取到原有的Service中Binder的實例。

    4.1.3 使用Service來處理後臺任務,Activity就可以放心地finish,完全不需要擔心無法對後臺任務進行控制的情況。

    4.1.4 我們可以在Service中再創建一個子線程,然後在這裏去處理耗時邏輯就沒問題了。

    4.1.5 較爲標準的Service寫法:

 

複製代碼
private MyBinder myBinder;


@Override  
public Binder onBind(Intent intent){
  return myBinder;
}

@Override  
public int onStartCommand(Intent intent, int flags, int startId) {  
    new Thread(new Runnable() {  
        @Override  
        public void run() {  
            // 開始執行後臺任務  
        }  
    }).start();  
    return super.onStartCommand(intent, flags, startId);  
}  
  
class MyBinder extends Binder {  
  
    public void startDownload() {  
        new Thread(new Runnable() {  
            @Override  
            public void run() {  
                // 執行具體的下載任務  
            }  
        }).start();  
    }  
  
}  
複製代碼

  4.2 Thread

    4.2.1 Thread是在子線程中運行的,旨在不影響主線程的運行。

           4.2.2 Activity很難對Thread進行控制,當Activity被銷燬之後,就沒有任何其它的辦法可以再重新獲取到之前創建的子線程的實例;

五、前臺Service

  5.1 需要在通知欄顯示,點擊之後,可以跳轉到Activity。優點,可以保持持續的運行。比如說墨跡天氣,它的Service在後臺更新天氣數據的同時,還會在系統狀態欄一直顯示當前天氣的信息。具體實現如下:

 

複製代碼
public class MyService extends Service {  
  
    public static final String TAG = "MyService";  
  
    private MyBinder mBinder = new MyBinder();  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
    //先定義通知
        Notification notification = new Notification(R.drawable.ic_launcher,  
                "有通知到來", System.currentTimeMillis());  
    //跳轉意圖
        Intent notificationIntent = new Intent(this, MainActivity.class);  
    //將意圖轉換爲等待意圖
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,  
                notificationIntent, 0);  
    //初始化通知
        notification.setLatestEventInfo(this, "這是通知的標題", "這是通知的內容",  
                pendingIntent);  
    //然後調用startForeground()方法就可以讓MyService變成一個前臺Service,並會將通知的圖片顯示出來。
        startForeground(1, notification);  
        Log.d(TAG, "onCreate() executed");  
    }  
  
    .........  
  
} 
複製代碼

 六、遠程Service

  6.1 遠程Service介紹:

        在註冊service的時候,添加屬性:remote即可激活遠程service。遠程service,是不同有主進程的service。直接可以在內部執行耗時操作,並且不影響主進程的使用。但是,有一個弊端。遠程service沒有辦法和Activity進行綁定。因爲,遠程service是不同於應用程序主進程的進程,他們之間無法建立連接的。

     那麼如何,才能使Activity和遠程service建立連接呢?這裏我們需要使用AIDL。接口定義語言來實現跨進程通信技術。

  6.2 AIDL(android interface definition language)的使用:

    6.2.1 使用方法,先建立一個後綴爲AIDL的文件,這是一個接口文件。然後進行編譯。系統會自動生成一個java文件。然後我們就可以進行使用了。

複製代碼
// IMyAidlInterface.aidl
package com.wangpei.service;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
   int plus(int a, int b);
   String toUpperCase(String str);
}
複製代碼

   6.2.2 然後進行編譯,系統會自動生成一個相應的java文件。此時,我們就可以使用它了。

在MyService中進行使用(對aidl中的方法,進行重寫。):

複製代碼
package com.wangpei.service;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

/**
 * 作者:WangPei on 2015/7/9 09:48
 * 郵箱:[email protected]
 */
public class myService extends Service {

    private static final String TAG = "myInfo";
    private MyBinder myBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
        @Override
        public int plus(int a, int b) throws RemoteException {
            return a+b;
        }

        @Override
        public String toUpperCase(String str) throws RemoteException {
            if(str != null){

            return str.toUpperCase();
            }else {
                return null;
            }
        }
    };


    @Override
    public void onCreate() {
        Log.i(TAG,"onCreate is excute");
//        Log.i(TAG,"myService thread is :"+Thread.currentThread().getName());



        /**
         * 前臺Service的使用
         */
//        Notification notification = new Notification(R.drawable.ic_launcher,"這是通知的內容",System.currentTimeMillis());
//        Intent notificationIntent = new Intent(this,MainActivity.class);
//        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
//        notification.setLatestEventInfo(this,"這是通知的標題","這是主要內容",pendingIntent);
//        startForeground(1,notification);

        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"onStartCommand is excute");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG,"onDestroy is excute");
        super.onDestroy();
    }

    class  MyBinder extends Binder{

        public void startDownload(){
            Log.i(TAG,"startDownload is excute");
        }
    }
}
複製代碼

  6.2.3 最後在Activity中進行調用,即可,使用Aidl中,所定義的方法。

複製代碼
 private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
//            myBinder = (myService.MyBinder) service;
//            myBinder.startDownload();
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                int result = iMyAidlInterface.plus(9,15);
                String str = iMyAidlInterface.toUpperCase("wang pei");

                Log.i(TAG,result+"");
                Log.i(TAG,str);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章