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<String, IBinder> 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> 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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容