之前使用Android綁定服務(wù)的功能跳昼,每次使用的時候都不是很方便,因為是異步的敲霍,代碼也比較多俊马,我現(xiàn)在想用同步的方式去調(diào)用服務(wù)的方法,一是代碼少肩杈,二是調(diào)用方便柴我。
之前嘗試先綁定服務(wù),然后保留得到的服務(wù)接口對象扩然,可是事與愿違艘儒,服務(wù)接口對象永不了多久就斷開連接了。翻看了TelephonyManager代碼夫偶,里面保存IBinder對象界睁,于是就嘗試保存服務(wù)的IBinder對象,需要調(diào)用服務(wù)的方法時通過IBinder對象去獲取服務(wù)對象接口兵拢,測試之后沒問題翻斟。
ServiceManager
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 java.util.Hashtable;
import java.util.List;
import java.util.Map;
/**
* 本地服務(wù)和遠程服務(wù)的管理器。
* 更加便捷的調(diào)用服務(wù)说铃,以一種同步的方法去調(diào)用服務(wù)方法访惜,
* 調(diào)用之前需要先做好前提工作,之后就可以以同步的方式去調(diào)用服務(wù)方法
* Created by 徐仕海 on 2017/5/13.
*/
public class ServiceManager {
private static ServiceManager instance;
/**
* 線程安全的到懶漢單例模式
*
* @return
*/
public static ServiceManager getDefault() {
ServiceManager tmp = instance;
if (tmp == null) {
synchronized (ServiceManager.class) {
instance = tmp = new ServiceManager();
}
}
return tmp;
}
private Map<String, IBinder> cache = new Hashtable<>();//線程安全的Map
/**
* 添加動作為action的服務(wù)(IBinder)到cache中
* 添加成功后便可以一直以同步的方法去調(diào)用服務(wù)方法截汪。
* 保存的IBinder對象不會像保存服務(wù)的接口對象會常常死掉疾牲。
* 以后每次使用服務(wù)的方法時聲稱一次服務(wù)的接口就可以了,方便又安全衙解。
*
* @param context
* @param action
*/
public void addService(final Context context, final String action) {
if (isIBinderEnabled(action))
return;
Intent intent = getExplicitIntent(context, new Intent(action));
if (intent == null)
return;
boolean ret = context.bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
cache.put(action, service);
context.unbindService(this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);
}
/**
* 獲取顯式的Intent,android5.0之后綁定服務(wù)只能是顯式Intent不能用隱式Intent.
*
* @param context
* @param implicitIntent
* @return
*/
private Intent getExplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> 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;
}
/**
* 獲取action對應(yīng)的服務(wù)的IBinder對象阳柔,這種對象可以用來生成可以直接使用的服務(wù)接口對象
*
* @param action
* @return
*/
public IBinder getService(String action) {
return cache.get(action);
}
/**
* 判斷action對應(yīng)的遠程服務(wù)的IBinder是否可用
*
* @param action
* @return
*/
public boolean isIBinderEnabled(String action) {
IBinder localBinder = getService(action);
return localBinder != null && localBinder.isBinderAlive();
}
}
DeviceManager
import android.content.Context;
import com.math.IMathAidlInterface;
/**
* Created by Administrator on 2017/5/13.
*/
public class DeviceManager extends ServiceManager {
private static DeviceManager instance;
/**
* 線程安全的到懶漢單例模式
*
* @return
*/
public static DeviceManager getDefault() {
DeviceManager tmp = instance;
if (tmp == null) {
synchronized (DeviceManager.class) {
instance = tmp = new DeviceManager();
}
}
return tmp;
}
/**********************************************************************************************************************/
final String ACTION_MATH = "com.math";
public void addMathService(Context context) {
addService(context, ACTION_MATH);
}
/**
* 將action對應(yīng)的遠程服務(wù)轉(zhuǎn)換成可用的IInterface
*
* @return
*/
public IMathAidlInterface getIMath() {
return IMathAidlInterface.Stub.asInterface(getService(ACTION_MATH));
}
}
使用方法
findViewById(R.id.tv_name).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IMathAidlInterface iMathAidlInterface = DeviceManager.getDefault().getIMath();
try {
Toast.makeText(MainActivity.this, "" + iMathAidlInterface.add(1, 33), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
DeviceManager.getDefault().addMathService(this);