一、在日常开发中,我们经常会遇到这样的需求就是网桌面添加快捷方式:常见的快捷方式有两种:一是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 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);
}
// 判读是否已经存在快捷方式
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;
}
注意要添加上对应的权限:首先在注册activity时,需要添加一个action为android.intent.action.CREATE_SHOERTCUT的intentFilter.如下所示:
接下来就是就是设置快捷方式的图标、名称、事件等属性。这里图表的生成,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);
}
}
}
四、快捷方式的手机适配问题:
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取一个别名。
在传递应用包名的时候,就传递我们取的别名