转载自: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下面:
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" ; 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)) { 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); } 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(); 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) { 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); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent()); 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>
在传递应用包名的时候,就传递我们取的别名