zoukankan      html  css  js  c++  java
  • 【转】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的源代码。位于packagesappsLauncher2srccomandroidlauncher2下面:

              

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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.   
    17. package com.android.launcher2;  
    18.   
    19. import java.util.ArrayList;  
    20.   
    21. import android.content.BroadcastReceiver;  
    22. import android.content.Context;  
    23. import android.content.Intent;  
    24. import android.widget.Toast;  
    25.   
    26. import com.android.launcher.R;  
    27.   
    28. public class InstallShortcutReceiver extends BroadcastReceiver {  
    29.     public static final String ACTION_INSTALL_SHORTCUT =  
    30.             "com.android.launcher.action.INSTALL_SHORTCUT";  
    31.   
    32.     // A mime-type representing shortcut data  
    33.     public static final String SHORTCUT_MIMETYPE =  
    34.             "com.android.launcher/shortcut";  
    35.   
    36.     private final int[] mCoordinates = new int[2];  
    37.   
    38.     public void onReceive(Context context, Intent data) {  
    39.         if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {  
    40.             return;  
    41.         }  
    42.   
    43.         int screen = Launcher.getScreen();  
    44.   
    45.         if (!installShortcut(context, data, screen)) {  
    46.             // The target screen is full, let's try the other screens  
    47.             for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {  
    48.                 if (i != screen && installShortcut(context, data, i)) break;  
    49.             }  
    50.         }  
    51.     }  
    52.   
    53.     private boolean installShortcut(Context context, Intent data, int screen) {  
    54.         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);  
    55.   
    56.         if (findEmptyCell(context, mCoordinates, screen)) {  
    57.             Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);  
    58.             if (intent != null) {  
    59.                 if (intent.getAction() == null) {  
    60.                     intent.setAction(Intent.ACTION_VIEW);  
    61.                 }  
    62.   
    63.                 // By default, we allow for duplicate entries (located in  
    64.                 // different places)  
    65.                 boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);  
    66.                 if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {  
    67.                     LauncherApplication app = (LauncherApplication) context.getApplicationContext();  
    68.                     app.getModel().addShortcut(context, data,  
    69.                             LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, mCoordinates[0],  
    70.                             mCoordinates[1], true);  
    71.                     Toast.makeText(context, context.getString(R.string.shortcut_installed, name),  
    72.                             Toast.LENGTH_SHORT).show();  
    73.                 } else {  
    74.                     Toast.makeText(context, context.getString(R.string.shortcut_duplicate, name),  
    75.                             Toast.LENGTH_SHORT).show();  
    76.                 }  
    77.   
    78.                 return true;  
    79.             }  
    80.         } else {  
    81.             Toast.makeText(context, context.getString(R.string.out_of_space),  
    82.                     Toast.LENGTH_SHORT).show();  
    83.         }  
    84.   
    85.         return false;  
    86.     }  
    87.   
    88.     private static boolean findEmptyCell(Context context, int[] xy, int screen) {  
    89.         final int xCount = LauncherModel.getCellCountX();  
    90.         final int yCount = LauncherModel.getCellCountY();  
    91.         boolean[][] occupied = new boolean[xCount][yCount];  
    92.   
    93.         ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);  
    94.         ItemInfo item = null;  
    95.         int cellX, cellY, spanX, spanY;  
    96.         for (int i = 0; i < items.size(); ++i) {  
    97.             item = items.get(i);  
    98.             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {  
    99.                 if (item.screen == screen) {  
    100.                     cellX = item.cellX;  
    101.                     cellY = item.cellY;  
    102.                     spanX = item.spanX;  
    103.                     spanY = item.spanY;  
    104.                     for (int x = cellX; x < cellX + spanX && x < xCount; x++) {  
    105.                         for (int y = cellY; y < cellY + spanY && y < yCount; y++) {  
    106.                             occupied[x][y] = true;  
    107.                         }  
    108.                     }  
    109.                 }  
    110.             }  
    111.         }  
    112.   
    113.         return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);  
    114.     }  
    115. }  

    通过以上源代码的阅读,我相信你基本了解创建的原理了。那么我们来实现自动创建快捷方式的逻辑。在activity中创建的代码:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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"属性,我们又不想重复创建,那么我们在创建之前就要判断是否存在快捷方式:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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.如下所示:

           

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <activity android:name="ShortCutTest">                
    2.         <intent-filter>                    
    3.             <action android:name="android.intent.action.CREATE_SHORTCUT"/>                
    4.         </intent-filter>            
    5.     </activity>  

          接下来就是就是设置快捷方式的图标、名称、事件等属性。这里图表的生成,android里提供了专门的方法来生成。  

        

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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.   
    9.     public void createShortCut(){             
    10.         Intent addShortCut;     
    11.         //判断是否需要添加快捷方式             
    12.         if(getIntent().getAction().equals(Intent.ACTION_CREATE_SHORTCUT)){                 
    13.             addShortCut = new Intent();                 
    14.             //快捷方式的名称                 
    15.             addShortCut.putExtra(Intent.EXTRA_SHORTCUT_NAME , "我的快捷方式");                 
    16.             //显示的图片                
    17.             Parcelable icon = ShortcutIconResource.fromContext(this, R.drawable.icon);                 
    18.             addShortCut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);     
    19.             //快捷方式激活的activity,需要执行的intent,自己定义                 
    20.             addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent());                 
    21.             //OK,生成                 
    22.             setResult(RESULT_OK, addShortCut);     
    23.         }else{                 
    24.              //取消                 
    25.             setResult(RESULT_CANCELED);     
    26.         }     
    27.     }     
    28. }   

    四、快捷方式的手机适配问题:
           在开发中我们还会遇到这样的情况,一个APP要创建多个快捷方式,但是对应的快捷方式打开的activity的类名又是一样的,
           例如:打开的都是activity都是com.test.MainActivity,然后根据传入的参数选择具体哪个tab下面的界面。例如创建语句为:

                 

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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取一个别名。
             

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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.   
    11.                 <category android:name="android.intent.category.DEFAULT" />  
    12.             </intent-filter>  
    13.         </activity-alias>  

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

  • 相关阅读:
    HTML、CSS、JS 复习——序
    HTML + CSS短标题(二,三,四文字长度)两端对齐的方式
    Supper关键字
    java的重写
    java重载
    Java继承
    JAVA访问权限控制
    (转)java类初始化顺序
    Java 数组和集合
    Java 方法签名
  • 原文地址:https://www.cnblogs.com/exmyth/p/5135212.html
Copyright © 2011-2022 走看看