http://blog.csdn.net/lenmoyouzi/article/details/16939977

一、在日常开发中,我们经常会遇到这样的需求就是网桌面添加快捷方式:常见的快捷方式有两种:一是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下面:

  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.launcher2;
  17. import java.util.ArrayList;
  18. import android.content.BroadcastReceiver;
  19. import android.content.Context;
  20. import android.content.Intent;
  21. import android.widget.Toast;
  22. import com.android.launcher.R;
  23. public class InstallShortcutReceiver extends BroadcastReceiver {
  24. public static final String ACTION_INSTALL_SHORTCUT =
  25. "com.android.launcher.action.INSTALL_SHORTCUT";
  26. // A mime-type representing shortcut data
  27. public static final String SHORTCUT_MIMETYPE =
  28. "com.android.launcher/shortcut";
  29. private final int[] mCoordinates = new int[2];
  30. public void onReceive(Context context, Intent data) {
  31. if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
  32. return;
  33. }
  34. int screen = Launcher.getScreen();
  35. if (!installShortcut(context, data, screen)) {
  36. // The target screen is full, let's try the other screens
  37. for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {
  38. if (i != screen && installShortcut(context, data, i)) break;
  39. }
  40. }
  41. }
  42. private boolean installShortcut(Context context, Intent data, int screen) {
  43. String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
  44. if (findEmptyCell(context, mCoordinates, screen)) {
  45. Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
  46. if (intent != null) {
  47. if (intent.getAction() == null) {
  48. intent.setAction(Intent.ACTION_VIEW);
  49. }
  50. // By default, we allow for duplicate entries (located in
  51. // different places)
  52. boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
  53. if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
  54. LauncherApplication app = (LauncherApplication) context.getApplicationContext();
  55. app.getModel().addShortcut(context, data,
  56. LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, mCoordinates[0],
  57. mCoordinates[1], true);
  58. Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
  59. Toast.LENGTH_SHORT).show();
  60. } else {
  61. Toast.makeText(context, context.getString(R.string.shortcut_duplicate, name),
  62. Toast.LENGTH_SHORT).show();
  63. }
  64. return true;
  65. }
  66. } else {
  67. Toast.makeText(context, context.getString(R.string.out_of_space),
  68. Toast.LENGTH_SHORT).show();
  69. }
  70. return false;
  71. }
  72. private static boolean findEmptyCell(Context context, int[] xy, int screen) {
  73. final int xCount = LauncherModel.getCellCountX();
  74. final int yCount = LauncherModel.getCellCountY();
  75. boolean[][] occupied = new boolean[xCount][yCount];
  76. ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
  77. ItemInfo item = null;
  78. int cellX, cellY, spanX, spanY;
  79. for (int i = 0; i < items.size(); ++i) {
  80. item = items.get(i);
  81. if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
  82. if (item.screen == screen) {
  83. cellX = item.cellX;
  84. cellY = item.cellY;
  85. spanX = item.spanX;
  86. spanY = item.spanY;
  87. for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
  88. for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
  89. occupied[x][y] = true;
  90. }
  91. }
  92. }
  93. }
  94. }
  95. return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);
  96. }
  97. }

通过以上源代码的阅读,我相信你基本了解创建的原理了。那么我们来实现自动创建快捷方式的逻辑。在activity中创建的代码:

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

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

  1. // 判读是否已经存在快捷方式
  2. public boolean isExistShortCut() {
  3. boolean isInstallShortcut = false;
  4. final ContentResolver cr = MainActivity.this.getContentResolver();
  5. // 本人的2.2系统是”com.android.launcher2.settings”,网上见其他的为"com.android.launcher.settings"
  6. final String AUTHORITY = "com.android.launcher2.settings";
  7. final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true");
  8. Cursor c = cr.query(CONTENT_URI, new String[] { "title", "iconResource" }, "title=?", new String[] { getString(R.string.app_name) }, null);
  9. if (c != null && c.getCount() > 0) {
  10. isInstallShortcut = true;
  11. System.out.println("已经存在快捷方式");
  12. }
  13. return isInstallShortcut;
  14. }

注意要添加上对应的权限:<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>   
三、通过系统长按方式实现的原理和上面差不多。单实现起来稍微要简单些。

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

  1. <activity android:name="ShortCutTest">
  2. <intent-filter>
  3. <action android:name="android.intent.action.CREATE_SHORTCUT"/>
  4. </intent-filter>
  5. </activity>

接下来就是就是设置快捷方式的图标、名称、事件等属性。这里图表的生成,android里提供了专门的方法来生成。

  1. public class ShortCutTest extends Activity{
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. // TODO Auto-generated method stub
  5. super.onCreate(savedInstanceState);
  6. createShortCut();
  7. }
  8. public void createShortCut(){
  9. Intent addShortCut;
  10. //判断是否需要添加快捷方式
  11. if(getIntent().getAction().equals(Intent.ACTION_CREATE_SHORTCUT)){
  12. addShortCut = new Intent();
  13. //快捷方式的名称
  14. addShortCut.putExtra(Intent.EXTRA_SHORTCUT_NAME , "我的快捷方式");
  15. //显示的图片
  16. Parcelable icon = ShortcutIconResource.fromContext(this, R.drawable.icon);
  17. addShortCut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
  18. //快捷方式激活的activity,需要执行的intent,自己定义
  19. addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent());
  20. //OK,生成
  21. setResult(RESULT_OK, addShortCut);
  22. }else{
  23. //取消
  24. setResult(RESULT_CANCELED);
  25. }
  26. }
  27. }

四、快捷方式的手机适配问题:
       在开发中我们还会遇到这样的情况,一个APP要创建多个快捷方式,但是对应的快捷方式打开的activity的类名又是一样的,
       例如:打开的都是activity都是com.test.MainActivity,然后根据传入的参数选择具体哪个tab下面的界面。例如创建语句为:

  1. ComponentName componentName = new ComponentName(context.getPackageName(), "com.test.MainActivity");
  2. Intent shortcutIntent = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
  3. shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, res.getString(nameResourceId));
  4. shortcutIntent.putExtra("duplicate", duplicate); // 是否允许重复创建
  5. shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(Intent.ACTION_MAIN).setComponent(componentName).putExtra("tab_contact_flag", tabPosition));
  6. shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, ((BitmapDrawable) res.getDrawable(iconResourceId)).getBitmap());
  7. context.sendBroadcast(shortcutIntent);

问题在于手机的适配,大部分手机会直接根据我们传入的:Intent.EXTRA_SHORTCUT_NAME对应的值去获取ApplicationInfo 的title.一些手机却根据我们传入的activity去找activity对应的name。由于我们传入的activity类名一样,所以获取到的ApplicationInfo 的title也是一样的。这时候的解决办法为跟activity取一个别名。

  1. <activity-alias
  2. android:name="com.test.tmpcontacts"
  3. android:clearTaskOnLaunch="true"
  4. android:icon="@drawable/ic_launcher_shortcut_contact"
  5. android:label="@string/shortcut_contact"
  6. android:launchMode="singleTask"
  7. android:targetActivity="com.test.MainActivity" >
  8. <intent-filter>
  9. <action android:name="android.intent.action.CREATE_SHORTCUT" />
  10. <category android:name="android.intent.category.DEFAULT" />
  11. </intent-filter>
  12. </activity-alias>

在传递应用包名的时候,就传递我们取的别名

【转】Android 快捷方式的创建的更多相关文章

  1. Android 快捷方式的创建与查询 快捷方式问题大全 获取快捷方式在Launcher数据库中的信息 Failed to find provider info for com.android.la

    /** * 创建添加快捷方式 * 其中需要设置的有: * 1. 快捷方式的标题 * 2. 快捷方式的图标 * 3. 点击快捷方式后的跳转 */ public static void createSho ...

  2. Android 快捷方式

    1. 需要权限: <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT&quo ...

  3. android 5.0 创建多用户 双开多开应用(2)

    上一讲 讲了如何创建一个user android 5.0 创建多用户 双开多开应用(1) 为什么要创建User  例如window 系统创建了一个user 会在当前用户下进行操作,而android 多 ...

  4. android2.3 View视图框架源码分析之一:android是如何创建一个view的?

    View是所有控件的一个基类,无论是布局(Layout),还是控件(Widget)都是继承自View类.只不过layout是一个特殊的view,它里面创建一个view的数组可以包含其他的view而已. ...

  5. android dom方式创建xml

    http://blog.csdn.net/nxh_love/article/details/7085174 在android dom 解析xml方式文章中,简单介绍了dom解析xml的应用.今天在原文 ...

  6. Android SD卡创建文件和文件夹失败

    原文:Android SD卡创建文件和文件夹失败 功能需要,尝试在本地sd卡上创建文件和文件夹的时候,报错,程序崩溃. 一般情况下,是忘记给予sd卡的读写权限.但是这里面权限已经给了,还是报错. 在网 ...

  7. Android Studio中创建Kotlin For Android项目

    Kotlin俗称Android中的Swift,它是Jetbrains公司开发的基于JVM的一门语言,JetBrains公司可能大家并不熟悉,不过相信IntelliJ IDE大家一定知道,Android ...

  8. 10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)

    1.Android数据库简单介绍. Android系统的framework层集成了Sqlite3数据库.我们知道Sqlite3是一种轻量级的高效存储的数据库. Sqlite数据库具有以下长处: (1) ...

  9. Android studio 中创建AIDL Service

      1.概述  AIDL在android系统中的作用 AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描写叙述语言, ...

随机推荐

  1. utube视频落地

    utube视频落地 简单粗暴的方法: 利用视频下载网站的网页版进行处理. 比如需要下载的视频的url是vid_url, 需要用到的web服务的url是web_service vid_url='http ...

  2. 双系统格式化硬盘后装XP遇到grub rescue的问题

    好奇于深度的Deepin系统,给老电脑装了xp和deepin双系统.无奈07年的机子带Deepin,实在是太卡了.正好想给硬盘重新分区,直接将硬盘格式化,重装了xp.于是,问题来了,开机显示: GRU ...

  3. python系统编码格式

    python在安装的时候默认的编码格式是ASCII,当程序中出现非ASCII编码时,python的处理常常会报这样的错UnicodeDecodeError,python没办法处理非ASCII编码的,此 ...

  4. Hibernate 多对一关系中,在多的一方进行数据的插入

    先看两个映射关系: 部门: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//H ...

  5. Swift与Objective-C中的闭包

    Swift Code: func makeIncrementor(forIncrement amount: Int) -> (() -> Int,() -> Int) { func ...

  6. Android Training精要(一)ActionBar上级菜单导航图标

    Navigation Up(ActionBar中的上级菜单导航图标) 在android 4.0中,我们需要自己维护activity之间的父子关系. 导航图标ID为android.R.id.home @ ...

  7. WebX配置文件、启动与响应流程

    ** 最近几天一直在看Spring的Ioc和AOP的源码介绍,还有Webx的使用.看Spring的源代码让人眼花缭乱,webx的配置文件也会让人感觉错综复杂无从下手.今天把之前看到的想到的webx相关 ...

  8. redis key expire

    EXPIRE key seconds 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除. 在 Redis 中,带有生存时间的 key 被称为『易失的』(volati ...

  9. USACO3.43Electric Fence(pick定理)

    忘记pick定理是什么了 想枚举来着 ..没枚出来 有篇pick定理的证明 貌似挺好 也没太看懂 /* ID: shangca2 LANG: C++ TASK: fence9 */ #include ...

  10. Javascript自动换图片

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...