转载自: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>
在传递应用包名的时候,就传递我们取的别名