Android快捷方式的创建

  • Post author:
  • Post category:其他


转载自: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>


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