Android的Launcher启动器中添加快捷方式及小部件实例

2019-12-10 18:54:46王旭

主工程逻辑如下:

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://www.easck.com/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 ;  
 } 
  
  
}