Android 实现 Launcher

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

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

             2 、"真"快捷方式 —— Activity具备<action/>为ACTION_CREATE_SHORTCUT的配置信息
 知识点介绍:

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

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

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

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

                附加值:EXTRA_INTENT  显示所有匹配显示所有匹配附加值为EXTRA_INTENT的Activity,

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

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

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

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

            我们快捷方式了。

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

    //重新发送一个Action为Pick_Activity的Intent,获取所有应用程序信息  
                  Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
                  Intent mainIntent = new Intent () ;  
                  mainIntent.setAction(Intent.ACTION_MAIN);  
                  mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
                    
                  pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);  
                  pickIntent.putExtra(Intent.EXTRA_TITLE, "选择应用程序"); //设置界面title  
                    
                  //继续选择所有应用程序  

                  startActivityForResult(pickIntent,MY_REQUEST_ALL_APPLICATION ); 



  知识点二、 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>


    package com.qin.addshortcut;  
      
    import java.util.ArrayList;  
      
    import android.app.Activity;  
    import android.content.ComponentName;  
    import android.content.Intent;  
    import android.content.Intent.ShortcutIconResource;  
    import android.content.pm.ActivityInfo;  
    import android.content.pm.PackageManager;  
    import android.content.pm.PackageManager.NameNotFoundException;  
    import android.content.res.Resources;  
    import android.graphics.Bitmap;  
    import android.graphics.Rect;  
    import android.graphics.drawable.BitmapDrawable;  
    import android.graphics.drawable.Drawable;  
    import android.os.Bundle;  
    import android.os.Parcelable;  
    import android.util.Log;  
    import android.view.LayoutInflater;  
    import android.view.View;  
    import android.widget.Button;  
    import android.widget.ImageView;  
    import android.widget.LinearLayout;  
    import android.widget.TextView;  
    import android.widget.Toast;  
    /**
     *  
     * @author http://http://blog.csdn.net/qinjuning
     */  
    public class MainActivity extends Activity implements View.OnClickListener  
    {  
      
        private LinearLayout linearlayout  ;   //用来存放所有快捷方式的容器 --- 父视图  
        private Button btAddShortCut;  
      
          
        private static final int MY_REQUEST_SHORT_CUT = 1;   //  第一步 、 显示所有能创建快捷方式的Activity  
        private static final int MY_CREATE_SHOURT_CUT = 2;         //第二步、 创建 真快捷方式  
        private static final int MY_REQUEST_ALL_APPLICATION = 3 ;  //第二步 、创建 伪快捷方式 -- 应用程序类  
        private static String TAG = "AddShortActivity" ;  
          
        private PackageManager mPackageManager = null ;  
          
        /** Called when the activity is first created. */  
        @Override  
        public void onCreate(Bundle savedInstanceState)  
        {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
      
            btAddShortCut = (Button) findViewById(R.id.bt_addShortcut);  
            linearlayout = (LinearLayout)findViewById(R.id.linearLayout) ;  
            linearlayout.setOnClickListener(this) ;  
              
            //演示如何通过一个资源的type获取该资源文件在R文件中的整数描述符  
            // getIdentifier 参数为 package:type/entry . 例如求icon的资源描述符如下:  
            int iconId = this.getResources().getIdentifier("com.qin.addshortcut:drawable/icon", null, null);          
            Log.i(TAG, " icon id : " + iconId);  
              
            //获取PackageManager对象  
            mPackageManager = getPackageManager();  
                     
            btAddShortCut.setOnClickListener(new View.OnClickListener()  
            {  
      
                @Override  
                public void onClick(View v)  
                {  
                    //创建快捷方式对话框  
                    createShortDialog() ;  
                }  
            });  
              
        }  
        private void createShortDialog(){  
              
            //begin :添加创建应用程序的图标('快捷方式")  
            // 此bundle值为附加的创建PICK_ACTIVITY的一个列表项  
            Bundle bundle = new Bundle() ;  
            //设置name  
            ArrayList<String> shortcutNames = new ArrayList<String>();  
            shortcutNames.add("应用程序");  
            bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);  
            //设置对应的头像  
            ArrayList<ShortcutIconResource> shortcutIconRes= new ArrayList<ShortcutIconResource>();  
            shortcutIconRes.add(ShortcutIconResource.fromContext(MainActivity.this, R.drawable.icon));  
            bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIconRes);  
            // end                 
              
            Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
      
            Intent extraIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);  
      
            pickIntent.putExtra(Intent.EXTRA_INTENT, extraIntent);//所要查找的Activity Intent  
            pickIntent.putExtra(Intent.EXTRA_TITLE, "选择快捷方式");  // Title  
            //看到没 , 伪快捷方式 是在这儿创建地。   
            pickIntent.putExtras(bundle);  
              
            startActivityForResult(pickIntent, MY_REQUEST_SHORT_CUT);   
        }  
          
          
        protected void onActivityResult(int requestCode, int resultCode, final Intent data)  
        {  
            super.onActivityResult(requestCode, resultCode, data);  
            //未成功的选择任何一个shortcut(比如直接按back键) , 直接返回  
            if(resultCode == RESULT_CANCELED )  
                return ;  
              
              
            switch(requestCode){  
            case MY_REQUEST_SHORT_CUT:  
                //第一次发送 PICK_Activity后 ,对所选列表项进行选择后,做的中间处理操作,需要判断是选择“应用程序” 抑或真正滴快捷方式  
                 // 获得快捷方式Label  
                String label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);  
                //这个字段是我们之前主动添加的  
                if(label.equals("应用程序")){    
                    //重新发送一个Action为Pick_Activity的Intent,获取所有应用程序信息  
                    Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);  
                    Intent mainIntent = new Intent () ;  
                    mainIntent.setAction(Intent.ACTION_MAIN);  
                    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
                      
                    pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);  
                    pickIntent.putExtra(Intent.EXTRA_TITLE, "选择应用程序"); //设置界面title  
                      
                    //继续选择所有应用程序  
                    startActivityForResult(pickIntent,MY_REQUEST_ALL_APPLICATION );  
                      
                }  
                else{  //重新请求创建上一次点击的Activity , 启动后即可创建   
                    Log.v(TAG, "MY_REQUEST_SHORT_CUT Intent Info--- >" + data);  
                    //下一步,创建某一具体的shortcut  
                    startActivityForResult(data, MY_CREATE_SHOURT_CUT);  
                }  
                break ;  
                  
            //以下操作才是真正地处理添加快捷方式的操作      
            case MY_CREATE_SHOURT_CUT:  
                //data数据封装了所有快捷方式应该该附加的值  
                Log.v(TAG, "MY_CREATE_SHOURT_CUT Intent Info--- >" + data);  
                completeAddShortCut(data);  
                break ;  
                  
            case MY_REQUEST_ALL_APPLICATION:    //创建一个应用程序的"快捷方式"  
                //data数据封装了点击某个应用程序的intent,包括action,ComponentName组信息等,继而我们可以通过intent对象获取该应用程序的信息  
                Log.v(TAG, "MY_REQUEST_ALL_APPLICATION Intent Info--- >" + data);  
                completeAddApplication(data)  ;  
                break ;  
            default :  
                break ;  
                  
            }  
              
        }  
          
        //添加一个应用程序的"快捷方式"  
        private void completeAddApplication(Intent data){  
              
            //打印应用程序返回的intent信息, 一个完整的启动应用程序的Intent  
            Log.i(TAG, "Application intent info ---->" +data) ;  
              
            ComponentName componentName = data.getComponent() ;  
            Log.i(TAG, "ComponentName Info ---->  " + componentName) ;  
              
            try  
            {  
                //获取资源图片  
                ActivityInfo activityInfo =  mPackageManager.getActivityInfo(componentName, 0);  
                CharSequence applabel = activityInfo.loadLabel(mPackageManager) ;  
                Drawable appIcon = activityInfo.loadIcon(mPackageManager) ;  
                  
                //创建一个View对象  
                View view  = makeViewForShortcut(applabel , appIcon) ;  
                //为该快捷方式的View设置onClick监听  
                view.setOnClickListener(this) ;  
                //将该intent对象设置为View的tag属性 , onClick时获取该tag  , --->getTag()  
                view.setTag(data) ;  
                  
                //将该View对象添加至LinearLayout中,由于大小发生了变化,系统会重新走”measure“ , ”layout“, ”draw“ 过程  
                //设置长宽高  
                LinearLayout.LayoutParams llparams = new LinearLayout.LayoutParams(80,90) ;  
                linearlayout.addView(view,llparams) ;  
            }  
            catch (NameNotFoundException e)  
            {  
                 Log.e(TAG, "NameNotFoundException  at completeAddApplication method") ;  
            }          
        }  
          
        //添加快捷方式(真正地,非应用程序)  
        private void completeAddShortCut(Intent data){  
              
            Drawable shortcutIcon = null;  //快捷方式的图标 , 可以有两种方式获取,如下 if else 判断  
          
            // 获得快捷方式Label  
            String label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);  
              
            Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);  
            // 直接了图片 , 即设置了 EXTRA_SHORTCUT_ICON 参数值  
            if (bitmap != null && bitmap instanceof Bitmap)  
            {  
                shortcutIcon = new BitmapDrawable((Bitmap) bitmap);  
            }  
            else   //设置了EXTRA_SHORTCUT_ICON_RESOURCE 附加值  
            {  
                Parcelable iconParcel = data .getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);  
                if(iconParcel != null && iconParcel instanceof ShortcutIconResource)  
                {  
                    // 获得ShortcutIconResource对象  
                    ShortcutIconResource iconRes = (ShortcutIconResource) iconParcel;  
                    //获得inconRes对象的Resource对象  
                    try  
                    {  
                        //获取对应packageName的Resources对象  
                        Resources resources = mPackageManager.getResourcesForApplication(iconRes.packageName);                  
                        //获取对应图片的id号  
                        int iconid = resources.getIdentifier(iconRes.resourceName, null, null);  
                        Log.i(TAG, "icon identifier is " + iconRes.resourceName) ;  
                        //获取资源图片  
                        shortcutIcon = resources.getDrawable(iconid);  
                    }  
                    catch (NameNotFoundException e)  
                    {  
                         Log.e(TAG, "NameNotFoundException  at completeAddShortCut method") ;  
                    }  
      
                }  
            }  
            //可能快捷方式没有为我们设置任何图像以及ShortcutIconResource对象,我们需要重置快捷方式的头像  
            if ( shortcutIcon == null) {  
                // 一定会有图片,这儿我简单的处理了 .  
                Toast.makeText(MainActivity.this, "sorry , we could not shortcut image", Toast.LENGTH_SHORT) ;  
                return ;  
            }  
      
            // 获得快捷方式Intent , 直接startActivity 即可  
            Intent shortcut_intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);  
              
            if (shortcut_intent != null)  
                Log.i(TAG, "shortCut intent info  ----> "+shortcut_intent) ;  
                      
            //创建一个View对象  
            View view  = makeViewForShortcut(label , shortcutIcon) ;  
            //为该快捷方式的View设置onClick监听  
            view.setOnClickListener(this) ;  
            //将该intent对象设置为View的tag属性 , onClick时获取该tag  , --->getTag()  
            view.setTag(shortcut_intent) ;  
              
            //将该View对象添加至LinearLayout中,由于大小发生了变化,系统会重新走”measure“ , ”layout“, ”draw“ 过程  
            //设置长宽高  
            LinearLayout.LayoutParams llparams = new LinearLayout.LayoutParams(100,90) ;  
              
            linearlayout.addView(view,llparams) ;  
         
        }  
      
        //点击事件  
        @Override  
        public void onClick(View v) {  
            Object tag = v.getTag() ;  
            if(tag !=null && tag instanceof Intent){  
                Intent intent = (Intent)tag ;  
                startActivityForSafely(intent) ;  
            }  
              
        }  
        //安全启动一个Activity  
        private void startActivityForSafely(Intent data) {  
            Intent launchIntent = data ;  
              
            //有些启动后的Activity需要设置该选项,即为启动的Activity设置一个界面,例如联系人的快捷方式, so , 我们加上它吧  
            launchIntent.setSourceBounds(new Rect(0,0,300,300));   
            launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
              
            startActivity(launchIntent) ;  
        }  
          
        //为每个快捷方式创建一个View对象  
        private View makeViewForShortcut(CharSequence label , Drawable icon){  
            LayoutInflater inflater = LayoutInflater.from(this) ;  
            View shortcut_view = inflater.inflate(R.layout.shortcut_view, null) ;  
              
            TextView tv = (TextView)shortcut_view.findViewById(R.id.shortcut_label) ;  
            tv.setText(label) ;  
              
            ImageView img = (ImageView)shortcut_view.findViewById(R.id.shortcut_img) ;  
            img.setImageDrawable(icon) ;  
            return shortcut_view ;        
        }  
           
    } 


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值