android ROM设置默认Launcher(主屏幕应用)

来源:互联网 发布:数据新闻比赛官网 编辑:程序博客网 时间:2024/05/20 16:34

Launcher

Launcher是android系统的桌面、是android系统的主要组件。android系统允许存在多个Launcher并设置默认主界面。

应用程序作为Home(主界面)需在Activity的intent-filter节点中添加如下内容

<category android:name="android.intent.category.HOME" /><category android:name="android.intent.category.DEFAULT" />

当系统中存在多个Home app且没有设置默认,用户点击Home键会弹出如下图所示的界面(图一):
这里写图片描述
用户可以选择“只有一次”或者“总是”来启动选择的APP

一般情况下android ROM中只会存在一个Home APP,系统启动后会直接启动此APP为默认,不需要用户选择。但是当ROM存在多个Home APP时,系统第一次启动就会弹出上图所示界面,让用户选择其中一个APP作为主屏幕应用,如果用户通过“ALWAYS”确认会设置选择的APP为默认的Home,用户通过“JUST ONCE”则此次以选择的APP为Home,再次按home键还是会弹出选择窗口


android ROM默认Launcher设置:

1:无效方案

网上有很多博客介绍如何设置ROM的默认Home app思路,都是在packages/apps/Provision/src/com/android/provision/DefaultActivity.java 中添加一段设置默认Home的代码,代码如下

    //网上的看到的    private void setupDefaultLauncher() {        // remove this activity from the package manager.        PackageManager pm = getPackageManager();        String examplePackageName = "******"; // package name        String exampleActivityName = "******"; // launcher activity name        ComponentName defaultLauncher = null;        Intent intent = new Intent(Intent.ACTION_MAIN);        intent.addCategory(Intent.CATEGORY_HOME);        List<ResolveInfo> resolveInfoList =                pm.queryIntentActivities(intent, 0);        if (resolveInfoList != null) {            int size = resolveInfoList.size();            for (int j = 0; j < size; ) {                final ResolveInfo r = resolveInfoList.get(j);                if (!r.activityInfo.packageName.equals(examplePackageName)) {                    resolveInfoList.remove(j);                    size -= 1;                } else {                    j++;                }            }            ComponentName[] set = new ComponentName[size];            defaultLauncher = new ComponentName(examplePackageName, exampleActivityName);            int defaultMatch = 0;            for (int i = 0; i < size; i++) {                final ResolveInfo resolveInfo =                        resolveInfoList.get(i);                Log.d(TAG, resolveInfo.toString());                set[i] = new                        ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);                if (defaultLauncher.getClassName().equals(resolveInfo.activityInfo.name)) {                    defaultMatch = resolveInfo.match;                }            }            Log.d(TAG, "defaultMatch =" + Integer.toHexString(defaultMatch));            IntentFilter filter = new IntentFilter();            filter.addAction(Intent.ACTION_MAIN);            filter.addCategory(Intent.CATEGORY_HOME);            filter.addCategory(Intent.CATEGORY_DEFAULT);            pm.clearPackagePreferredActivities(defaultLauncher.getPackageName());            pm.addPreferredActivity(filter, defaultMatch, set, defaultLauncher);        }    }    //系统设置中修改默认Launcher的代码,    private void setupDefaultLauncher2() {    String packageName = "******"; // package name        PackageManager mPm = getPackageManager();        ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();        ComponentName currentDefaultHome  = mPm.getHomeActivities(homeActivities);        IntentFilter mHomeFilter = new IntentFilter(Intent.ACTION_MAIN);        mHomeFilter.addCategory(Intent.CATEGORY_HOME);        mHomeFilter.addCategory(Intent.CATEGORY_DEFAULT);        ComponentName[] mHomeComponentSet = new ComponentName[homeActivities.size()];        int prefIndex = 0;        for (int i = 0; i < homeActivities.size(); i++) {            final ResolveInfo candidate = homeActivities.get(i);            final ActivityInfo info = candidate.activityInfo;            ComponentName activityName = new ComponentName(info.packageName, info.name);            mHomeComponentSet[i] = activityName;            if(info.packageName.equals(packageName)){                currentDefaultHome = activityName;            }        }        mPm.replacePreferredActivity(mHomeFilter, IntentFilter.MATCH_CATEGORY_EMPTY,                mHomeComponentSet, currentDefaultHome);    }

将以上任何一段代码添加到DefaultActivityonCreate方法中,都无法实现修改启动后的默认Launcher,只能使设置的默认Launcher为选中状态如下图(图二):
Launcher选择窗口

2:有效方案

既然使用上述设置默认主界面的做法无效,而在上述界面选择却有效,那么就从上面弹出的选择默认主界面的界面入手,通过追踪发现上述界面是一个Activity,Activity代码路径frameworks/base/core/java/com/android/internal/app/ResolverActivity.java

  • ResolverActivity分析

此Activity会获取系统中所有的Home app,并根据系统的设置情况显示如上界面。此类中有一个内部类ResolveListAdapter该类继承自BaseAdapter,该类是Home app选择界面的数据适配器。

ResolveListAdapter会在ResolverActivity的onCreate方法中被初始化并会传入一个ResolveInfo类型的List,ResolveListAdapter根据会传入的List<ResolveInfo>初始化一个List<DisplayResolveInfo> mList ,用户的点击事件都会在ResolveListAdapter获取数据。
用户点击”ALWAYS”的事件发生在ResolverActivity的onButtonClick 方法中,此方法会获取选中的Item的position、或者获取用户上一次启动的Home app的,mAlwaysUseOption代表用户选中的是否为历史选择(如2图中的Launcher3),并调用startSelected。

    public void onButtonClick(View v) {        final int id = v.getId();        startSelected(mAlwaysUseOption ?                mListView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),                id == R.id.button_always,                mAlwaysUseOption);        dismiss();    }

StartSeletced中通过ResolveListAdapter获取选择的item代表的Home app。并且finish此activity
onIntentSelected会根据传入的ResolveInfo设置默认的Home,并根据Intent跳转到相应界面,onIntentSelected的代码在这里就不列出。

    /**     * 设置默认Home app并跳转,结束此Activity     * @param which 用户选择的Item的position     * @param always 是否设置为总是     * @param filtered 是否非历史选择     */    void startSelected(int which, boolean always, boolean filtered) {        if (isFinishing()) {            return;        }        ResolveInfo ri = mAdapter.resolveInfoForPosition(which, filtered);        Intent intent = mAdapter.intentForPosition(which, filtered);        //设置默认Home,并启动        onIntentSelected(ri, intent, always);        finish();    }

ResolveListAdapter的相关代码

        /**        *        * @param position         * @param filtered        * @return         */        public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {            //mList为List<DisplayResolveInfo>            return (filtered ? getItem(position) : mList.get(position)).ri;        }        /**        *         * @param position        * @param filtered        * @return         */        public Intent intentForPosition(int position, boolean filtered) {            //mList为List<DisplayResolveInfo>            DisplayResolveInfo dri = filtered ? getItem(position) : mList.get(position);            return intentForDisplayResolveInfo(dri);        }

解决办法

此Activity的onCreate方法中判断是否为第一次启动,如果是则调用startSelected方法设置默认Home app。

默认Home app的从ResolveListAdapter中获取,所以在ResolveListAdapter中添加getDefaultHomePosition(String packageName)方法,用于获取默认home app在List<DisplayResolveInfo> 中的位置,代码如下:

        public int getDefaultHomePosition(String packageName){            for (int i = 0; i < mList.size(); i++) {                ResolveInfo info = mList.get(i).ri;                if (DEBUG)                Log.w(TAG,"getDefaultHomePosition " + info.activityInfo.packageName);                if (info.activityInfo.packageName.equals(packageName)) {                   return i;                }            }            return -1;        }

ResolverActivity中添加设置默认app的方法setupDefaultLauncher(),代码如下:

    //用于记录默认home app是否设置过    private static final String DEFAULT_HOME = "persist.sys.default.home";    private void setupDefaultLauncher() {        String first = "";        try{            first =  SystemProperties.get(DEFAULT_HOME);        }catch(Exception e){            Log.w(TAG,"exception error get DEFAULT_HOME");        }        //判断默认home 是否设置过,如果获取的字符串为空代表,未设置,否则return不在进行设置        if (!TextUtils.isEmpty(first)) {            return;        }        //使用包名获取所需设置的默认home app在ResolveListAdapter中的位置        int position = mAdapter.getDefaultHomePosition("home app包名");        //如果不存在则return        if (position == -1) {            if (DEBUG)            Log.w(TAG,"not find default Home");            return;        }        //设置默认home app后,则添加记录        try{            SystemProperties.set(DEFAULT_HOME,DEFAULT_HOME);        }catch(Exception e){            Log.w(TAG,"exception error set DEFAULT_HOME");        }        //设置默认home app,并跳转        startSelected(position, true, true);        //结束此activity        dismiss();    }

为了保证mAdapter被初始化 setupDefaultLauncher()的调用添加到ResolverActivity的onCreate函数中,代码如下:

    protected void onCreate(Bundle savedInstanceState, Intent intent,            CharSequence title, int defaultTitleRes, Intent[] initialIntents,            List<ResolveInfo> rList, boolean alwaysUseOption) {        //其他初始化代码        ............        mIntent = new Intent(intent);        mAdapter = new ResolveListAdapter(this, initialIntents, rList,                mLaunchedFromUid, alwaysUseOption);        //其它初始化代码        ............        if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {            // Gulp!            finish();            return;        }        int count = mAdapter.mList.size();        //添加的代码        setupDefaultLauncher();        //原有逻辑        //如果系统中home app大于1        if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {            //初始化代码            .........        //如果home app等于1则设置唯一的home app为Home        } else if (count == 1) {            safelyStartActivity(mAdapter.intentForPosition(0, false));            mPackageMonitor.unregister();            mRegistered = false;            finish();            return;        } else {            setContentView(R.layout.resolver_list);            final TextView empty = (TextView) findViewById(R.id.empty);            empty.setVisibility(View.VISIBLE);            mListView = (ListView) findViewById(R.id.resolver_list);            mListView.setVisibility(View.GONE);        }        //其它初始化代码        ..........    }

通过以上方法即可实现设置默认home的功能

0 0
原创粉丝点击