Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> AndroidStudio 使用AIDL

AndroidStudio 使用AIDL

編輯:關於Android編程

一直以來都認為AIDL的應用離我很遙遠,甚至不知道如何去用,也就懶得去學,之前的項目中也看到過aidl文件,只是懶得去看而已,現在感覺自己真的是無藥可救了,如果只止步於學習一些UI調整的東西談何進步,不過有些東西也真是逼著去學的,要學的東西太多了,只要隔著一段時間不用的話,估計學習的東西又都忘完了,不說了,開始講正事,也算給自己留個筆記,長時間不用再回來看看。

1、為什麼要有AIDL?

對於AIDL有一些人(包括我自己)的淺顯概念就是:AIDL可以跨進程訪問其他應用程序,和其他應用程序通訊,那我告訴你,很多技術都可以訪問,如廣播(應用A在AndroidManifest.xml中注冊指定Action的廣播)應用B發送指定Action的廣播,A就能收到信息,這樣也能看成不同應用之間完成了通訊(但是這種通訊是單向的);還如ContentProvider,通過URI接口暴露數據給其他應用訪問;但是這種都算不上是應用之間的通訊。可能最讓人迷惑的是Android推出來了Messager,它就是完成應用之間的通訊的。那麼為什麼還要有AIDL呢,官方文檔介紹AIDL中有這麼一句話:

Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.

第一句最重要,“只有當你允許來自不同的客戶端訪問你的服務並且需要處理多線程問題時你才必須使用AIDL”,其他情況下你都可以選擇其他方法,如使用Messager,也能跨進程通訊。可見AIDL是處理多線程、多客戶端並發訪問的。而Messager是單線程處理。還是官方文檔說的明白,一句話就可以理解為什麼要有AIDL。一直認為理論應與實踐相結合,這樣才利於學習,由於現在用的是android studio ,所以就用的AS開發的一個AIDL小demo。

2、AIDL使用

2.1、在android studio中創建一個工程

2.2、創建兩個module 比如我的: aidlserver和app這樣就能實現兩個進程了。

圖1\

2.3、在aidlserver中的創建aidl文件見下圖

圖2\

2.3.1、在你新建的aidl中聲明你的服務方法,此處聲明了add和min兩個方法,代碼如下

 // ICalcAIDL.aidl
package com.liujc.aidlserver;
// Declare any non-default types here with import statements
interface ICalcAIDL {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    int add(int x , int y);
    int min(int x , int y );
}

2.3.2、在工具欄中build該module,生成ICalcAIDL對應的java代碼,如下

圖3\ 圖4\

2.3.3、在對用的java文件夾下創建對應的service,例如圖中的CalcService,代碼如下:

package com.liujc.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class CalcService extends Service {
    private static final String TAG = "server";


    public void onCreate()
    {
        Log.e(TAG, "onCreate");
    }


    public IBinder onBind(Intent t)
    {
        Log.e(TAG, "onBind");
        return mBinder;
    }


    public void onDestroy()
    {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }


    public boolean onUnbind(Intent intent)
    {
        Log.e(TAG, "onUnbind");
        return super.onUnbind(intent);
    }


    public void onRebind(Intent intent)
    {
        Log.e(TAG, "onRebind");
        super.onRebind(intent);
    }


    private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()
    {


        @Override
        public int add(int x, int y) throws RemoteException
        {
            return x + y;
        }


        @Override
        public int min(int x, int y) throws RemoteException
        {
            return x - y;
        }


    };
}

2.3.4、在mainifest文件中聲明service,如下:

<service android:name=".CalcService" android:process=":remote">
            <intent-filter>
                <action android:name="com.liujc.aidlserver.CalcService">
                <category android:name="android.intent.category.DEFAULT">
            </category></action></intent-filter>
        </service>

2.4、將aidlserver中的aidl包,直接copy到app中(客戶端的aidl包必須和服務端一致,否則會序列化失敗,無法bindservice),如下圖,同時也要和步驟2.3.2一樣生成相應的java代碼。

圖5\

2.5、實現客戶端和服務端的綁定代碼

package com.liujc.utdemo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.liujc.aidlserver.ICalcAIDL;

import java.util.List;

public class MainActivity extends Activity {
    private ICalcAIDL mCalcAidl;
    private ServiceConnection mServiceConn = new ServiceConnection()
    {
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            Log.e("client", "onServiceDisconnected");
            mCalcAidl = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            Log.e("client", "onServiceConnected");
            mCalcAidl = ICalcAIDL.Stub.asInterface(service);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    /**
     * 點擊BindService按鈕時調用
     * @param view
     */
    public void bindService(View view)
    {
        Intent intent = new Intent("com.liujc.aidlserver.CalcService");
//        intent.setAction("com.liujc.aidlserver.CalcService");
        final Intent eintent = new Intent(createExplicitFromImplicitIntent(this,intent));
        bindService(eintent, mServiceConn, Context.BIND_AUTO_CREATE);
    }
    /**
     * 點擊unBindService按鈕時調用
     * @param view
     */
    public void unbindService(View view)
    {
        if (mServiceConn != null)
        unbindService(mServiceConn);
    }
    /**
     * 點擊12+12按鈕時調用
     * @param view
     */
    public void addInvoked(View view) throws Exception
    {

        if (mCalcAidl != null)
        {
            int addRes = mCalcAidl.add(12, 12);
            Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
        } else
        {
            Toast.makeText(this, "服務器被異常殺死,請重新綁定服務端", Toast.LENGTH_SHORT)
                    .show();

        }

    }
    /**
     * 點擊50-12按鈕時調用
     * @param view
     */
    public void minInvoked(View view) throws Exception
    {

        if (mCalcAidl != null)
        {
            int addRes = mCalcAidl.min(58, 12);
            Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
        } else
        {
            Toast.makeText(this, "服務端未綁定或被異常殺死,請重新綁定服務端", Toast.LENGTH_SHORT)
                    .show();

        }

    }

    public  Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
        // Retrieve all services that can match the given intent
        PackageManager pm = context.getPackageManager();
        List resolveInfo = pm.queryIntentServices(implicitIntent, 0);

        // Make sure only one match was found
        if (resolveInfo == null || resolveInfo.size() != 1) {
            return null;
        }

        // Get component info and create ComponentName
        ResolveInfo serviceInfo = resolveInfo.get(0);
        String packageName = serviceInfo.serviceInfo.packageName;
        String className = serviceInfo.serviceInfo.name;
        ComponentName component = new ComponentName(packageName, className);

        // Create a new intent. Use the old one for extras and such reuse
        Intent explicitIntent = new Intent(implicitIntent);

        // Set the component to be explicit
        explicitIntent.setComponent(component);

        return explicitIntent;
    }
}
OK,今天先到這裡
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved