Android 快捷方式的创建

一、在日常开发中,我们经常会遇到这样的需求就是网桌面添加快捷方式:常见的快捷方式有两种:一是APP的快捷方式,一是widget插件的快捷方式。下面详细介绍这两种情况的应用:

   参考网站:http://www.cnblogs.com/lhxin/archive/2012/05/30/2526525.html

                      http://blog.csdn.net/xubin341719/article/details/7059285

二、APP的快捷方式:

      1、 app快捷方式的实现又有两种情况,一是直接在桌面生成;一是通过长按桌面,在弹出的快捷菜单中生成。

      2、直接生成快捷方式主要是通过发送系统广播InstallShortcutReceiver实现的。

           我们先来看一下InstallShortcutReceiver的源代码。位于packages\apps\Launcher2\src\com\android\launcher2下面:

          

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.launcher2;

import java.util.ArrayList;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

import com.android.launcher.R;

public class InstallShortcutReceiver extends BroadcastReceiver {
    public static final String ACTION_INSTALL_SHORTCUT =
            "com.android.launcher.action.INSTALL_SHORTCUT";

    // A mime-type representing shortcut data
    public static final String SHORTCUT_MIMETYPE =
            "com.android.launcher/shortcut";

    private final int[] mCoordinates = new int[2];

    public void onReceive(Context context, Intent data) {
        if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
            return;
        }

        int screen = Launcher.getScreen();

        if (!installShortcut(context, data, screen)) {
            // The target screen is full, let's try the other screens
            for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {
                if (i != screen && installShortcut(context, data, i)) break;
            }
        }
    }

    private boolean installShortcut(Context context, Intent data, int screen) {
        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);

        if (findEmptyCell(context, mCoordinates, screen)) {
            Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
            if (intent != null) {
                if (intent.getAction() == null) {
                    intent.setAction(Intent.ACTION_VIEW);
                }

                // By default, we allow for duplicate entries (located in
                // different places)
                boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
                if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
                    LauncherApplication app = (LauncherApplication) context.getApplicationContext();
                    app.getModel().addShortcut(context, data,
                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, mCoordinates[0],
                            mCoordinates[1], true);
                    Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context, context.getString(R.string.shortcut_duplicate, name),
                            Toast.LENGTH_SHORT).show();
                }

                return true;
            }
        } else {
            Toast.makeText(context, context.getString(R.string.out_of_space),
                    Toast.LENGTH_SHORT).show();
        }

        return false;
    }

    private static boolean findEmptyCell(Context context, int[] xy, int screen) {
        final int xCount = LauncherModel.getCellCountX();
        final int yCount = LauncherModel.getCellCountY();
        boolean[][] occupied = new boolean[xCount][yCount];

        ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
        ItemInfo item = null;
        int cellX, cellY, spanX, spanY;
        for (int i = 0; i < items.size(); ++i) {
            item = items.get(i);
            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
                if (item.screen == screen) {
                    cellX = item.cellX;
                    cellY = item.cellY;
                    spanX = item.spanX;
                    spanY = item.spanY;
                    for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
                        for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
                            occupied[x][y] = true;
                        }
                    }
                }
            }
        }

        return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);
    }
}
通过以上源代码的阅读,我相信你基本了解创建的原理了。那么我们来实现自动创建快捷方式的逻辑。在activity中创建的代码:

private void createShortcut() {
        Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
        shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, getString(R.string.app_name));
        shortcut.putExtra("duplicate", false);//设置是否重复创建
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setClass(this, WelcomeActivity.class);//设置第一个页面
        shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
        ShortcutIconResource iconRes = Intent.ShortcutIconResource.fromContext(this, R.drawable.logo);
        shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes);
        sendBroadcast(shortcut);
    }

如果在创建快捷方式的时候,我们没有指定“duplicate"属性,我们又不想重复创建,那么我们在创建之前就要判断是否存在快捷方式:

// 判读是否已经存在快捷方式
    public boolean isExistShortCut() {
        boolean isInstallShortcut = false;
        final ContentResolver cr = MainActivity.this.getContentResolver();
        // 本人的2.2系统是”com.android.launcher2.settings”,网上见其他的为"com.android.launcher.settings"
        final String AUTHORITY = "com.android.launcher2.settings";
        final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true");
        Cursor c = cr.query(CONTENT_URI, new String[] { "title", "iconResource" }, "title=?", new String[] { getString(R.string.app_name) }, null);
        if (c != null && c.getCount() > 0) {
            isInstallShortcut = true;
            System.out.println("已经存在快捷方式");
        }
        return isInstallShortcut;
    }
注意要添加上对应的权限:<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>   
三、通过系统长按方式实现的原理和上面差不多。单实现起来稍微要简单些。

       首先在注册activity时,需要添加一个action为android.intent.action.CREATE_SHOERTCUT的intentFilter.如下所示:

       

<activity android:name="ShortCutTest">              
        <intent-filter>                  
            <action android:name="android.intent.action.CREATE_SHORTCUT"/>              
        </intent-filter>          
    </activity>
      接下来就是就是设置快捷方式的图标、名称、事件等属性。这里图表的生成,android里提供了专门的方法来生成。  

    

public class ShortCutTest extends Activity{       
    @Override      
    protected void onCreate(Bundle savedInstanceState) {           
    // TODO Auto-generated method stub           
    super.onCreate(savedInstanceState);       
        createShortCut();
    }   

    public void createShortCut(){           
        Intent addShortCut;   
        //判断是否需要添加快捷方式           
        if(getIntent().getAction().equals(Intent.ACTION_CREATE_SHORTCUT)){               
            addShortCut = new Intent();               
            //快捷方式的名称               
            addShortCut.putExtra(Intent.EXTRA_SHORTCUT_NAME , "我的快捷方式");               
            //显示的图片              
            Parcelable icon = ShortcutIconResource.fromContext(this, R.drawable.icon);               
            addShortCut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);   
            //快捷方式激活的activity,需要执行的intent,自己定义               
            addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent());               
            //OK,生成               
            setResult(RESULT_OK, addShortCut);   
        }else{               
             //取消               
            setResult(RESULT_CANCELED);   
        }   
    }   
} 
四、快捷方式的手机适配问题:
       在开发中我们还会遇到这样的情况,一个APP要创建多个快捷方式,但是对应的快捷方式打开的activity的类名又是一样的,
       例如:打开的都是activity都是com.test.MainActivity,然后根据传入的参数选择具体哪个tab下面的界面。例如创建语句为:

             

ComponentName componentName = new ComponentName(context.getPackageName(), "com.test.MainActivity");
		Intent shortcutIntent = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
		shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, res.getString(nameResourceId));
		shortcutIntent.putExtra("duplicate", duplicate); // 是否允许重复创建
		shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(Intent.ACTION_MAIN).setComponent(componentName).putExtra("tab_contact_flag", tabPosition));
		shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, ((BitmapDrawable) res.getDrawable(iconResourceId)).getBitmap());
		context.sendBroadcast(shortcutIntent);
        问题在于手机的适配,大部分手机会直接根据我们传入的:Intent.EXTRA_SHORTCUT_NAME对应的值去获取ApplicationInfo 的title.一些手机却根据我们传入的activity去找activity对应的name。由于我们传入的activity类名一样,所以获取到的ApplicationInfo 的title也是一样的。这时候的解决办法为跟activity取一个别名。
         
<activity-alias
            android:name="com.test.tmpcontacts"
            android:clearTaskOnLaunch="true"
            android:icon="@drawable/ic_launcher_shortcut_contact"
            android:label="@string/shortcut_contact"
            android:launchMode="singleTask"
            android:targetActivity="com.test.MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.CREATE_SHORTCUT" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity-alias>
         在传递应用包名的时候,就传递我们取的别名




  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值