【转】Android 快捷方式的创建
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下面:
- /*
 - * 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>
 
在传递应用包名的时候,就传递我们取的别名
【转】Android 快捷方式的创建的更多相关文章
- Android 快捷方式的创建与查询  快捷方式问题大全  获取快捷方式在Launcher数据库中的信息 Failed to find provider info for com.android.la
		
/** * 创建添加快捷方式 * 其中需要设置的有: * 1. 快捷方式的标题 * 2. 快捷方式的图标 * 3. 点击快捷方式后的跳转 */ public static void createSho ...
 - Android 快捷方式
		
1. 需要权限: <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT&quo ...
 - android 5.0 创建多用户 双开多开应用(2)
		
上一讲 讲了如何创建一个user android 5.0 创建多用户 双开多开应用(1) 为什么要创建User 例如window 系统创建了一个user 会在当前用户下进行操作,而android 多 ...
 - android2.3 View视图框架源码分析之一:android是如何创建一个view的?
		
View是所有控件的一个基类,无论是布局(Layout),还是控件(Widget)都是继承自View类.只不过layout是一个特殊的view,它里面创建一个view的数组可以包含其他的view而已. ...
 - android dom方式创建xml
		
http://blog.csdn.net/nxh_love/article/details/7085174 在android dom 解析xml方式文章中,简单介绍了dom解析xml的应用.今天在原文 ...
 - Android SD卡创建文件和文件夹失败
		
原文:Android SD卡创建文件和文件夹失败 功能需要,尝试在本地sd卡上创建文件和文件夹的时候,报错,程序崩溃. 一般情况下,是忘记给予sd卡的读写权限.但是这里面权限已经给了,还是报错. 在网 ...
 - Android Studio中创建Kotlin For Android项目
		
Kotlin俗称Android中的Swift,它是Jetbrains公司开发的基于JVM的一门语言,JetBrains公司可能大家并不熟悉,不过相信IntelliJ IDE大家一定知道,Android ...
 - 10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)
		
1.Android数据库简单介绍. Android系统的framework层集成了Sqlite3数据库.我们知道Sqlite3是一种轻量级的高效存储的数据库. Sqlite数据库具有以下长处: (1) ...
 - Android studio 中创建AIDL Service
		
1.概述 AIDL在android系统中的作用 AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描写叙述语言, ...
 
随机推荐
- Leetcode 解题 Longest Substring without repeating charcater python
			
原题: Given a string, find the length of the longest substring without repeating character For example ...
 - POJ 3349 Snowflake Snow Snowflakes      Hash
			
题目链接: http://poj.org/problem?id=3349 #include <stdio.h> #include <string.h> #include < ...
 - PDF判断打印是A4还是B5
			
打印材料通畅就是这样两个规格,之前经常受其困扰,B5规格达成A4会显得字很大,当然本身A4就跟大:如果是A4打成B5字很小的: 其实,判断依据就是Adobe reader里面的,当鼠标滑向左下角的时候 ...
 - RESTheart官方文档
			
作者:Andrea Di Cesare, Maurizio Turatti RESTHeart是SoftInstigate公司创建并开发的开源项目. MongoDB的WEB操作接口 RESTHEART ...
 - EF4 Code First和EF6 Code First链接mysql的方法
			
1.首先需要下载安装.Net的Mysql驱动 下载地址如下:http://dev.mysql.com/downloads/connector/net/ 2.配置Web.Config EF6: 配置链接 ...
 - Word2003中如何使封面和目录中不插入页码
			
Word2003中如何使封面和目录中不插入页码?? 转载自: http://blog.zzedu.net.cn/user1/zhaoweijie/archives/2010/187266.html ...
 - WINDOWS WMI--这是一个神奇的应用
			
运行:wbemtest.exe
 - draw9patch超详细教程
			
这篇文章是android开发人员的必备知识,内容摘选自网络,友我为大家整理和总结,不求完美,但是有用. 视频教程地址:http://player.youku.com/player.php/sid/XM ...
 - 猜测:信号槽的本质是使用Windows的自定义消息来实现的
			
在不断执行: void MyTool::DeleteAllFiles(){ for (i = 0; i <= n - 1; i++) { // do something }}在for循环没有执行 ...
 - 【Xamarin挖墙脚系列:在VMware11中安装Mac10.11 EI Captain后的vmware tools】
			
原文:[Xamarin挖墙脚系列:在VMware11中安装Mac10.11 EI Captain后的vmware tools] 如何安装 darwin.iso,百度去吧. 关键是对应版本的darwin ...