• Android中实现Launcher功能之一 添加快捷方式



                                                                                                                                            

                                                                                                                                      转载请注明出处:http://blog.csdn.net/qinjuning

              前言: 最近一直在看Launcher模块,经过差不多两个月学习,终于摸透了Launcher的一些主要功能实现,目前继续还处于

      摸索状态。未看Launcher时,于我而言,只能膜拜,以为所有功能都是它实现的 ;入门后,才发现,Launcher的很多功能只是

      集成了框架/应用程序提供的功能。很多陌生的东西,只有接触了才感叹:“oh ,原来是这样的!”

        

            今天先给大家分享下Launcher如何实现添加快捷方式(Shortcut) ,后续会慢慢增加其他方面的功能,帮助大家“一叶而知秋”。

            具体来说,Launcher中的快捷方式有两种类型:

                 1 、"伪"快捷方式 —— 应用程序类型

                 2 、"真"快捷方式 —— Activity具备<action/>为ACTION_CREATE_SHORTCUT的配置信息

           这两种类型的快捷方式是怎么勾搭在一起的,在下面大家通过代码自己理解,也不方便细说了。

          

            关于如何创建一个”真”快捷方式(Shortcut)的App ,大家可以先去看看杨丰盛老师的博客《Android特色开发之桌面组》 ,

         从中我们可以掌握如何创建一个快捷方式,实现也不是很难。

       

     知识点介绍:

         知识点一 、ACTION_PICK_ACTIVITY使用说明 ,具体可以参考SDK Intent

                    功能:显示匹配附加值为EXTRA_INTENT所有Activity,并将它们以列表呈现给用户。当用户从该列表选中一项  

           时,并不会启动该Activity(这与与ACTION_CHOOSER不同,此Action会启动用户选择的Activity),而是将该Activity的详细信

           息(可能包括Action、ComponentName、data信息等)以Intent对象返回给调用者(通常为onActivityResult方法)。

                  

                    附加值:EXTRA_INTENT  显示所有匹配显示所有匹配附加值EXTRA_INTENTActivity,

                                    EXTRA_TITLE     作为显示列表即所有Activity的标题 。

            

           因此,根据ACTION_PICK_ACTIVITY的特性,真正地创建快捷方式需要两步走:

                

                 第一步:发送ACTION_PICK_ACTIVITY以及EXTRA_INTENT找到我们希望能创建快捷方式的Activity列表。

          第二步:根据第一步所选择的Activity返回的Intent对象,再次发送此Intent对象,即可创建该Activity提供给

                我们快捷方式了。

              例如,下面我们只是简单的发送一个请求显示所有应用程序的Intent,如下:

    1. //重新发送一个Action为Pick_Activity的Intent,获取所有应用程序信息  
    2.               Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
    3.               Intent mainIntent = new Intent () ;  
    4.               mainIntent.setAction(Intent.ACTION_MAIN);  
    5.               mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
    6.                 
    7.               pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);  
    8.               pickIntent.putExtra(Intent.EXTRA_TITLE, "选择应用程序"); //设置界面title  
    9.                 
    10.               //继续选择所有应用程序  
    11.               startActivityForResult(pickIntent,MY_REQUEST_ALL_APPLICATION );  


     

          ACTION_PICK_ACTIVITY效果图如下:

            

                          

            点击某一具体Activity  , 即可选择创建该Activity的快捷方式了。

      知识点二、 Intent.ShortcutIconResource类介绍

                            功能: 为快捷方式(Shortcut)和文件夹(live folder)提供图片资源

         常用方法为:

               public static Intent.ShortcutIconResource fromContext(Context context, int resourceId)

                 功能: 创建一个 Intent.ShortcutIconResource 对象

                 参数说明:context        Context类对象

                                     resourceId  具体的图片资源id 。

     

         常用属性:

                 packageName    该应用程序所在包名,类型为 packageName:type/entityname

                 resourceName   resourceId所对应地的资源名

     

          例如 某个图片资源 R.id.icon = 0x7f020000, 则resourceName 为 packageName:drawable/icon

     

     

         具体怎么通过 Intent.ShortcutIconResource对象获取图片资源,请参考示例Demo。

     

    示例Demo 

              说明:点击创建快捷方式对话框后, 选择某一项具体的快捷方式,即可添加至MainActivity界面中 ,继续点击每个View,则

        可启动该快快捷方式的App,挺给力的吧。

              PS: 由于我只是简单的利用了LinearLayout去当容器,会存在局限性,大家可在此基础上,利用GridView/ListView构建更好

         的布局,当然更NB的是,去提供类似Launcher的自定义布局。

           

             由于执行快捷方式可能需要一些特定的权限,因此我们必须得在AndroidManifest.xml里配置对应的权限。例如,直接拨打电话

       需要的权限为:   <uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>

              如上效果图,增加几个快捷方式后截图如下,点击即可启动该应用。

                                                                    

          

     主工程逻辑如下:

    1. package com.qin.addshortcut;  
    2.   
    3. import java.util.ArrayList;  
    4.   
    5. import android.app.Activity;  
    6. import android.content.ComponentName;  
    7. import android.content.Intent;  
    8. import android.content.Intent.ShortcutIconResource;  
    9. import android.content.pm.ActivityInfo;  
    10. import android.content.pm.PackageManager;  
    11. import android.content.pm.PackageManager.NameNotFoundException;  
    12. import android.content.res.Resources;  
    13. import android.graphics.Bitmap;  
    14. import android.graphics.Rect;  
    15. import android.graphics.drawable.BitmapDrawable;  
    16. import android.graphics.drawable.Drawable;  
    17. import android.os.Bundle;  
    18. import android.os.Parcelable;  
    19. import android.util.Log;  
    20. import android.view.LayoutInflater;  
    21. import android.view.View;  
    22. import android.widget.Button;  
    23. import android.widget.ImageView;  
    24. import android.widget.LinearLayout;  
    25. import android.widget.TextView;  
    26. import android.widget.Toast;  
    27. /** 
    28.  *  
    29.  * @author http://http://blog.csdn.net/qinjuning 
    30.  */  
    31. public class MainActivity extends Activity implements View.OnClickListener  
    32. {  
    33.   
    34.     private LinearLayout linearlayout  ;   //用来存放所有快捷方式的容器 --- 父视图  
    35.     private Button btAddShortCut;  
    36.   
    37.       
    38.     private static final int MY_REQUEST_SHORT_CUT = 1;   //  第一步 、 显示所有能创建快捷方式的Activity  
    39.     private static final int MY_CREATE_SHOURT_CUT = 2;         //第二步、 创建 真快捷方式  
    40.     private static final int MY_REQUEST_ALL_APPLICATION = 3 ;  //第二步 、创建 伪快捷方式 -- 应用程序类  
    41.     private static String TAG = "AddShortActivity" ;  
    42.       
    43.     private PackageManager mPackageManager = null ;  
    44.       
    45.     /** Called when the activity is first created. */  
    46.     @Override  
    47.     public void onCreate(Bundle savedInstanceState)  
    48.     {  
    49.         super.onCreate(savedInstanceState);  
    50.         setContentView(R.layout.main);  
    51.   
    52.         btAddShortCut = (Button) findViewById(R.id.bt_addShortcut);  
    53.         linearlayout = (LinearLayout)findViewById(R.id.linearLayout) ;  
    54.         linearlayout.setOnClickListener(this) ;  
    55.           
    56.         //演示如何通过一个资源的type获取该资源文件在R文件中的整数描述符  
    57.         // getIdentifier 参数为 package:type/entry . 例如求icon的资源描述符如下:  
    58.         int iconId = this.getResources().getIdentifier("com.qin.addshortcut:drawable/icon"nullnull);          
    59.         Log.i(TAG, " icon id : " + iconId);  
    60.           
    61.         //获取PackageManager对象  
    62.         mPackageManager = getPackageManager();  
    63.                  
    64.         btAddShortCut.setOnClickListener(new View.OnClickListener()  
    65.         {  
    66.   
    67.             @Override  
    68.             public void onClick(View v)  
    69.             {  
    70.                 //创建快捷方式对话框  
    71.                 createShortDialog() ;  
    72.             }  
    73.         });  
    74.           
    75.     }  
    76.     private void createShortDialog(){  
    77.           
    78.         //begin :添加创建应用程序的图标('快捷方式")  
    79.         // 此bundle值为附加的创建PICK_ACTIVITY的一个列表项  
    80.         Bundle bundle = new Bundle() ;  
    81.         //设置name  
    82.         ArrayList<String> shortcutNames = new ArrayList<String>();  
    83.         shortcutNames.add("应用程序");  
    84.         bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);  
    85.         //设置对应的头像  
    86.         ArrayList<ShortcutIconResource> shortcutIconRes= new ArrayList<ShortcutIconResource>();  
    87.         shortcutIconRes.add(ShortcutIconResource.fromContext(MainActivity.this, R.drawable.icon));  
    88.         bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIconRes);  
    89.         // end                 
    90.           
    91.         Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
    92.   
    93.         Intent extraIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);  
    94.   
    95.         pickIntent.putExtra(Intent.EXTRA_INTENT, extraIntent);//所要查找的Activity Intent  
    96.         pickIntent.putExtra(Intent.EXTRA_TITLE, "选择快捷方式");  // Title  
    97.         //看到没 , 伪快捷方式 是在这儿创建地。   
    98.         pickIntent.putExtras(bundle);  
    99.           
    100.         startActivityForResult(pickIntent, MY_REQUEST_SHORT_CUT);   
    101.     }  
    102.       
    103.       
    104.     protected void onActivityResult(int requestCode, int resultCode, final Intent data)  
    105.     {  
    106.         super.onActivityResult(requestCode, resultCode, data);  
    107.         //未成功的选择任何一个shortcut(比如直接按back键) , 直接返回  
    108.         if(resultCode == RESULT_CANCELED )  
    109.             return ;  
    110.           
    111.           
    112.         switch(requestCode){  
    113.         case MY_REQUEST_SHORT_CUT:  
    114.             //第一次发送 PICK_Activity后 ,对所选列表项进行选择后,做的中间处理操作,需要判断是选择“应用程序” 抑或真正滴快捷方式  
    115.              // 获得快捷方式Label  
    116.             String label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);  
    117.             //这个字段是我们之前主动添加的  
    118.             if(label.equals("应用程序")){    
    119.                 //重新发送一个Action为Pick_Activity的Intent,获取所有应用程序信息  
    120.                 Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
    121.                 Intent mainIntent = new Intent () ;  
    122.                 mainIntent.setAction(Intent.ACTION_MAIN);  
    123.                 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
    124.                   
    125.                 pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);  
    126.                 pickIntent.putExtra(Intent.EXTRA_TITLE, "选择应用程序"); //设置界面title  
    127.                   
    128.                 //继续选择所有应用程序  
    129.                 startActivityForResult(pickIntent,MY_REQUEST_ALL_APPLICATION );  
    130.                   
    131.             }  
    132.             else{  //重新请求创建上一次点击的Activity , 启动后即可创建   
    133.                 Log.v(TAG, "MY_REQUEST_SHORT_CUT Intent Info--- >" + data);  
    134.                 //下一步,创建某一具体的shortcut  
    135.                 startActivityForResult(data, MY_CREATE_SHOURT_CUT);  
    136.             }  
    137.             break ;  
    138.               
    139.         //以下操作才是真正地处理添加快捷方式的操作      
    140.         case MY_CREATE_SHOURT_CUT:  
    141.             //data数据封装了所有快捷方式应该该附加的值  
    142.             Log.v(TAG, "MY_CREATE_SHOURT_CUT Intent Info--- >" + data);  
    143.             completeAddShortCut(data);  
    144.             break ;  
    145.               
    146.         case MY_REQUEST_ALL_APPLICATION:    //创建一个应用程序的"快捷方式"  
    147.             //data数据封装了点击某个应用程序的intent,包括action,ComponentName组信息等,继而我们可以通过intent对象获取该应用程序的信息  
    148.             Log.v(TAG, "MY_REQUEST_ALL_APPLICATION Intent Info--- >" + data);  
    149.             completeAddApplication(data)  ;  
    150.             break ;  
    151.         default :  
    152.             break ;  
    153.               
    154.         }  
    155.           
    156.     }  
    157.       
    158.     //添加一个应用程序的"快捷方式"  
    159.     private void completeAddApplication(Intent data){  
    160.           
    161.         //打印应用程序返回的intent信息, 一个完整的启动应用程序的Intent  
    162.         Log.i(TAG, "Application intent info ---->" +data) ;  
    163.           
    164.         ComponentName componentName = data.getComponent() ;  
    165.         Log.i(TAG, "ComponentName Info ---->  " + componentName) ;  
    166.           
    167.         try  
    168.         {  
    169.             //获取资源图片  
    170.             ActivityInfo activityInfo =  mPackageManager.getActivityInfo(componentName, 0);  
    171.             CharSequence applabel = activityInfo.loadLabel(mPackageManager) ;  
    172.             Drawable appIcon = activityInfo.loadIcon(mPackageManager) ;  
    173.               
    174.             //创建一个View对象  
    175.             View view  = makeViewForShortcut(applabel , appIcon) ;  
    176.             //为该快捷方式的View设置onClick监听  
    177.             view.setOnClickListener(this) ;  
    178.             //将该intent对象设置为View的tag属性 , onClick时获取该tag  , --->getTag()  
    179.             view.setTag(data) ;  
    180.               
    181.             //将该View对象添加至LinearLayout中,由于大小发生了变化,系统会重新走”measure“ , ”layout“, ”draw“ 过程  
    182.             //设置长宽高  
    183.             LinearLayout.LayoutParams llparams = new LinearLayout.LayoutParams(80,90) ;  
    184.             linearlayout.addView(view,llparams) ;  
    185.         }  
    186.         catch (NameNotFoundException e)  
    187.         {  
    188.              Log.e(TAG, "NameNotFoundException  at completeAddApplication method") ;  
    189.         }          
    190.     }  
    191.       
    192.     //添加快捷方式(真正地,非应用程序)  
    193.     private void completeAddShortCut(Intent data){  
    194.           
    195.         Drawable shortcutIcon = null;  //快捷方式的图标 , 可以有两种方式获取,如下 if else 判断  
    196.       
    197.         // 获得快捷方式Label  
    198.         String label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);  
    199.           
    200.         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);  
    201.         // 直接了图片 , 即设置了 EXTRA_SHORTCUT_ICON 参数值  
    202.         if (bitmap != null && bitmap instanceof Bitmap)  
    203.         {  
    204.             shortcutIcon = new BitmapDrawable((Bitmap) bitmap);  
    205.         }  
    206.         else   //设置了EXTRA_SHORTCUT_ICON_RESOURCE 附加值  
    207.         {  
    208.             Parcelable iconParcel = data .getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);  
    209.             if(iconParcel != null && iconParcel instanceof ShortcutIconResource)  
    210.             {  
    211.                 // 获得ShortcutIconResource对象  
    212.                 ShortcutIconResource iconRes = (ShortcutIconResource) iconParcel;  
    213.                 //获得inconRes对象的Resource对象  
    214.                 try  
    215.                 {  
    216.                     //获取对应packageName的Resources对象  
    217.                     Resources resources = mPackageManager.getResourcesForApplication(iconRes.packageName);                  
    218.                     //获取对应图片的id号  
    219.                     int iconid = resources.getIdentifier(iconRes.resourceName, nullnull);  
    220.                     Log.i(TAG, "icon identifier is " + iconRes.resourceName) ;  
    221.                     //获取资源图片  
    222.                     shortcutIcon = resources.getDrawable(iconid);  
    223.                 }  
    224.                 catch (NameNotFoundException e)  
    225.                 {  
    226.                      Log.e(TAG, "NameNotFoundException  at completeAddShortCut method") ;  
    227.                 }  
    228.   
    229.             }  
    230.         }  
    231.         //可能快捷方式没有为我们设置任何图像以及ShortcutIconResource对象,我们需要重置快捷方式的头像  
    232.         if ( shortcutIcon == null) {  
    233.             // 一定会有图片,这儿我简单的处理了 .  
    234.             Toast.makeText(MainActivity.this"sorry , we could not shortcut image", Toast.LENGTH_SHORT) ;  
    235.             return ;  
    236.         }  
    237.   
    238.         // 获得快捷方式Intent , 直接startActivity 即可  
    239.         Intent shortcut_intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);  
    240.           
    241.         if (shortcut_intent != null)  
    242.             Log.i(TAG, "shortCut intent info  ----> "+shortcut_intent) ;  
    243.                   
    244.         //创建一个View对象  
    245.         View view  = makeViewForShortcut(label , shortcutIcon) ;  
    246.         //为该快捷方式的View设置onClick监听  
    247.         view.setOnClickListener(this) ;  
    248.         //将该intent对象设置为View的tag属性 , onClick时获取该tag  , --->getTag()  
    249.         view.setTag(shortcut_intent) ;  
    250.           
    251.         //将该View对象添加至LinearLayout中,由于大小发生了变化,系统会重新走”measure“ , ”layout“, ”draw“ 过程  
    252.         //设置长宽高  
    253.         LinearLayout.LayoutParams llparams = new LinearLayout.LayoutParams(100,90) ;  
    254.           
    255.         linearlayout.addView(view,llparams) ;  
    256.      
    257.     }  
    258.   
    259.     //点击事件  
    260.     @Override  
    261.     public void onClick(View v) {  
    262.         Object tag = v.getTag() ;  
    263.         if(tag !=null && tag instanceof Intent){  
    264.             Intent intent = (Intent)tag ;  
    265.             startActivityForSafely(intent) ;  
    266.         }  
    267.           
    268.     }  
    269.     //安全启动一个Activity  
    270.     private void startActivityForSafely(Intent data) {  
    271.         Intent launchIntent = data ;  
    272.           
    273.         //有些启动后的Activity需要设置该选项,即为启动的Activity设置一个界面,例如联系人的快捷方式, so , 我们加上它吧  
    274.         launchIntent.setSourceBounds(new Rect(0,0,300,300));   
    275.         launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
    276.           
    277.         startActivity(launchIntent) ;  
    278.     }  
    279.       
    280.     //为每个快捷方式创建一个View对象  
    281.     private View makeViewForShortcut(CharSequence label , Drawable icon){  
    282.         LayoutInflater inflater = LayoutInflater.from(this) ;  
    283.         View shortcut_view = inflater.inflate(R.layout.shortcut_view, null) ;  
    284.           
    285.         TextView tv = (TextView)shortcut_view.findViewById(R.id.shortcut_label) ;  
    286.         tv.setText(label) ;  
    287.           
    288.         ImageView img = (ImageView)shortcut_view.findViewById(R.id.shortcut_img) ;  
    289.         img.setImageDrawable(icon) ;  
    290.         return shortcut_view ;        
    291.     }  
    292.       
    293.       
    294. }  



      

               某些快捷方式的功能实现起来还是很炫彩的 , 尤其是启动直接拨打、直接发送短信的Activity,最开始我以为是Launcher实

     现地,如今才明白原来是快捷方式提供了一个Intent对象,Launcher直接采用了拿来主义了。 不多说了,大家慢慢感受体味吧。

                  示例DEMO下载地址: http://download.csdn.net/detail/qinjuning/4008605

  • 相关阅读:
    Openlayers2中vector扩展FeatureLayer
    点图层叠加与事件响应
    geoserver服务wfs之GetFeature
    Echart在Openlayers的应用-航班的炫光特效
    Echart在Openlayers的应用-热力图
    Echart在Openlayers的应用
    WMS图例展示
    Java新手锻炼
    Java动手又动脑
    java递归问题小程序
  • 原文地址:https://www.cnblogs.com/wanqieddy/p/2484535.html
Copyright © 2020-2023  润新知