android ServiceManager

之前使用Android绑定服务的功能,每次使用的时候都不是很方便,因为是异步的,代码也比较多,我现在想用同步的方式去调用服务的方法,一是代码少,二是调用方便。

之前尝试先绑定服务,然后保留得到的服务接口对象,可是事与愿违,服务接口对象永不了多久就断开连接了。翻看了TelephonyManager代码,里面保存IBinder对象,于是就尝试保存服务的IBinder对象,需要调用服务的方法时通过IBinder对象去获取服务对象接口,测试之后没问题。

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;

/**
 * 本地服务和远程服务的管理器。
 * 更加便捷的调用服务,以一种同步的方法去调用服务方法,
 * 调用之前需要先做好前提工作,之后就可以以同步的方式去调用服务方法
 * 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 cache = new Hashtable<>();//线程安全的Map


    /**
     * 添加动作为action的服务(IBinder)到cache中
     * 添加成功后便可以一直以同步的方法去调用服务方法。
     * 保存的IBinder对象不会像保存服务的接口对象会常常死掉。
     * 以后每次使用服务的方法时声称一次服务的接口就可以了,方便又安全。
     *
     * @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之后绑定服务只能是显式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 = 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对应的服务的IBinder对象,这种对象可以用来生成可以直接使用的服务接口对象
     *
     * @param action
     * @return
     */
    public IBinder getService(String action) {
        return cache.get(action);
    }

    /**
     * 判断action对应的远程服务的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对应的远程服务转换成可用的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);

你可能感兴趣的:(android ServiceManager)