例のPackageManager - Package nameからApplication Icon、name取得と他Application起動

昨日のPostで宣言した通り例のごとくPackageManagerについてのPostになります。ActivityManagerと連携してRecentTaskのListに載っているTaskの起動をしてみたいと思います。下記のScreen shotのようにApplication iconやApplication nameを取得し表示、さらにはitemをclickしてそのApplicationを起動出来ます(Home button長押しで出てくるTask managerみたいな機能)


PackageManagerとは

DeviceにinstallされているApplicationの様々な情報を取得することができる(ここ参照)

実装の要点は下記です

  1. PackageManager objectを取得
  2. (ApplicationManagerを使い取得した)Package nameからApplicationInfo objectを取得
  3. ApplicationInfoからapplication iconを取得
  4. ApplicationInfoからapplication nameを取得
  5. PackageManagerを使いApplicationをlaunchする為のIntentを取得

んで実装です

AndroidManifest.xml(ActivityManagerの回と変わらず)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.android.practice"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ActivityManagerPractice"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <!-- Task情報取得のためにAndroidManifest.xmlにandroid.permission.GET_TASKSを記載 -->
    <uses-permission android:name="android.permission.GET_TASKS" />
</manifest>

Activity

package com.android.practice;


import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;

public class ActivityManagerPractice extends Activity implements View.OnClickListener{
	
	private static final String TAG = "ActivityManagerPractice";
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setOnClickListeners();
    }
    
    private void setOnClickListeners(){
    	((Button)findViewById(R.id.process_display_button)).setOnClickListener(this);
    	((Button)findViewById(R.id.recent_task_display_button)).setOnClickListener(this);
    	((Button)findViewById(R.id.running_task_display_button)).setOnClickListener(this);
    }

	@Override
	public void onClick(View v) {
		final ListView lv = new ListView(this);
		BaseAdapter adapter = null;
		String title = null;
		switch(v.getId()){
		case R.id.process_display_button:
			adapter = new ProcessAdapter(this);
			title = "Process";
			lv.setOnItemClickListener((ProcessAdapter)adapter);
			break;
		case R.id.recent_task_display_button:
			adapter = new RecentTaskAdapter(this);
			title = "Recent Task";
			lv.setOnItemClickListener((RecentTaskAdapter)adapter);
			break;
		case R.id.running_task_display_button:
			adapter = new RunningTaskAdapter(this);
			title = "Running Task";
			lv.setOnItemClickListener((RunningTaskAdapter)adapter);
			break;
		default:
			return;
		}
		
		showListDialog(this, lv, adapter, title);
	}
	
	private void showListDialog(Context context, ListView lv, BaseAdapter adapter, String title){
		lv.setAdapter(adapter);
		
		final AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setTitle(title);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
				dialog = null;
			}
		});
		builder.setView(lv);
		
		builder.create().show();
	}
}

PackageManager、ActivityManger取得class(抽象なAdapter拡張class)

package com.android.practice;

import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.pm.PackageManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

abstract public class AbsActivityManagerAdapter<T> extends BaseAdapter {
	
	final protected Context mContext;
	final protected ActivityManager mActivityMgr;
	final protected PackageManager mPackageMgr;
	protected List<T> mInfoList;
	
	public AbsActivityManagerAdapter(Context context){
		mContext = context;
		//ActivityManager objectを取得
		mActivityMgr = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
		//PackageManager objectを取得		
		mPackageMgr = context.getPackageManager();
		mInfoList = createList();
	}
	
	@Override
	public int getCount() {
		if(mInfoList == null){
			return 0;
		}
		return mInfoList.size();
	}

	@Override
	public Object getItem(int position) {
		if(mInfoList == null || position < 0 || position >= mInfoList.size()){
			return null;
		}
		return mInfoList.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view = convertView;
		if(view == null){
			view = getListItemLayout();
			ViewHolder viewHolder = createViewHolder(view);
			view.setTag(viewHolder);
		}
		
		setContentsToViewHolder(view, position);
		
		return view;
	}
	
	abstract protected List<T> createList();
	abstract protected View getListItemLayout();
	abstract protected ViewHolder createViewHolder(View view);
	abstract protected void setContentsToViewHolder(View view, int position);
	
	public static interface ViewHolder{
		
	}
}

RunningAppProcessInfo取得class

package com.android.practice;

import java.util.List;

import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;


public class ProcessAdapter extends AbsActivityManagerAdapter<RunningAppProcessInfo> implements OnItemClickListener{
	
	private static final String TAG = "ProcessAdapter";
	
	public ProcessAdapter(Context context) {
		super(context);
	}
	
	@Override
	protected View getListItemLayout(){
		LayoutInflater lInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		return lInflater.inflate(R.layout.process, null);
	}
	
	@Override
	protected ViewHolder createViewHolder(View view){
		ProcessListViewHolder viewHolder = new ProcessListViewHolder();
		viewHolder.mImage = (ImageView)view.findViewById(R.id.icon);
		viewHolder.mApplicationText = (TextView)view.findViewById(R.id.application);
		viewHolder.mPackageText = (TextView)view.findViewById(R.id.pkg);
		viewHolder.mProcessText = (TextView)view.findViewById(R.id.process);
		viewHolder.mImportanceText = (TextView)view.findViewById(R.id.importance);
		viewHolder.mImportanceReasonText = (TextView)view.findViewById(R.id.importance_reason);
		return viewHolder;
	}
	
	@Override
	protected void setContentsToViewHolder(View view, int position){
		ProcessListViewHolder viewHolder = (ProcessListViewHolder)view.getTag();
		ApplicationInfo appInfo = null;
		String pkgName = mInfoList.get(position).pkgList[0];
		
		try {
			if(pkgName != null){
				//Package nameからApplicationInfo objectを取得
				appInfo = mPackageMgr.getApplicationInfo(pkgName, 0);
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		
		if(appInfo != null){
			//ApplicationInfoからapplication iconを取得
			Drawable appIcon = appInfo.loadIcon(mPackageMgr);
			viewHolder.mImage.setImageDrawable(appIcon);
			//ApplicationInfoからapplication nameを取得
			String appName = (String) appInfo.loadLabel(mPackageMgr);
			viewHolder.mApplicationText.setText("Application: " + appName);
		}
		
		viewHolder.mPackageText.setText("Package: " + pkgName);
		//Process nameの取得。基本はPackage nameと一緒
		viewHolder.mProcessText.setText("Process: " + mInfoList.get(position).processName);
		viewHolder.mImportanceText.setText("Importance: "  + mInfoList.get(position).importance);
		viewHolder.mImportanceReasonText.setText("ImportanceReason: " +  + mInfoList.get(position).importanceReasonCode);
	}

	@Override
	protected List<RunningAppProcessInfo> createList() {
		//RunningAppProcessInfoのListを取得
		return mActivityMgr.getRunningAppProcesses();
	}
	
	public static class ProcessListViewHolder implements ViewHolder{
		public ImageView mImage;
		public TextView mApplicationText;
		public TextView mPackageText;
		public TextView mProcessText;
		public TextView mImportanceText;
		public TextView mImportanceReasonText;
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		String pkgName = mInfoList.get(position).pkgList[0];
		//PackageManagerを使いApplicationをlaunchする為のIntentを取得
		Intent intent = mPackageMgr.getLaunchIntentForPackage(pkgName);
		if(intent == null){
			Log.d(TAG, "intent null");
			return;
		}
		mContext.startActivity(intent);
	}
}

RecentTaskInfo取得class

package com.android.practice;

import java.util.List;

import com.android.practice.AbsActivityManagerAdapter.ViewHolder;
import com.android.practice.ProcessAdapter.ProcessListViewHolder;

import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.TextView;

public class RecentTaskAdapter extends AbsActivityManagerAdapter<RecentTaskInfo> implements OnItemClickListener{
	
	private static final String TAG = "RecentTaskAdapter";
	
	public RecentTaskAdapter(Context context) {
		super(context);
	}

	@Override
	protected List<RecentTaskInfo> createList() {
		//RecentTaskInfoのListを取得
		return mActivityMgr.getRecentTasks(100, 0);
	}

	@Override
	protected View getListItemLayout() {
		LayoutInflater lInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		return lInflater.inflate(R.layout.recent_task, null);
	}

	@Override
	protected ViewHolder createViewHolder(View view) {
		RecentTaskListViewHolder viewHolder = new RecentTaskListViewHolder();
		viewHolder.mImage = (ImageView)view.findViewById(R.id.recent_task_app_icon);
		viewHolder.mApplicationText = (TextView)view.findViewById(R.id.recent_task_app_name);
		viewHolder.mPackageText = (TextView)view.findViewById(R.id.recent_task_pkg_name);
		return viewHolder;
	}

	@Override
	protected void setContentsToViewHolder(View view, int position) {
		RecentTaskListViewHolder viewHolder = (RecentTaskListViewHolder)view.getTag();
		ApplicationInfo appInfo = null;
		//Taskを起動したIntentを取得
		Intent intent =  mInfoList.get(position).baseIntent;
		String pkgName = intent.getComponent().getPackageName();
		
		try {
			if(pkgName != null){
				//Package nameからApplicationInfo objectを取得
				appInfo = mPackageMgr.getApplicationInfo(pkgName, 0);
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		
		if(appInfo != null){
			//ApplicationInfoからapplication iconを取得
			Drawable appIcon = appInfo.loadIcon(mPackageMgr);
			viewHolder.mImage.setImageDrawable(appIcon);
			//ApplicationInfoからapplication nameを取得
			String appName = (String) appInfo.loadLabel(mPackageMgr);
			viewHolder.mApplicationText.setText("Application: " + appName);
		}

		//ComponentName objectからPackageNameを取得
		viewHolder.mPackageText.setText("Package: " + pkgName);
	}
	
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		Intent intent = mInfoList.get(position).baseIntent;
		if(intent == null){
			Log.d(TAG, "intent null");
			return;
		}
		mContext.startActivity(intent);
	}
	
	public static class RecentTaskListViewHolder implements ViewHolder{
		public ImageView mImage;
		public TextView mApplicationText;
		public TextView mPackageText;
	}
}

RunningTaskInfo取得class

package com.android.practice;

import java.util.List;

import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class RunningTaskAdapter extends AbsActivityManagerAdapter<RunningTaskInfo> implements OnItemClickListener{
	
	private static final String TAG = "RunningTaskAdapter";
	
	public RunningTaskAdapter(Context context) {
		super(context);
	}

	@Override
	protected List<RunningTaskInfo> createList() {
		//RunningTaskInfoのListを取得
		return mActivityMgr.getRunningTasks(100);
	}

	@Override
	protected View getListItemLayout() {
		LayoutInflater lInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		return lInflater.inflate(R.layout.running_task, null);
	}

	@Override
	protected ViewHolder createViewHolder(View view) {
		RunningTaskListViewHolder viewHolder = new RunningTaskListViewHolder();
		viewHolder.mImage = (ImageView)view.findViewById(R.id.running_task_app_icon);
		viewHolder.mApplicationText = (TextView)view.findViewById(R.id.running_task_app_name);
		viewHolder.mPackageText = (TextView)view.findViewById(R.id.running_task_pkg_name);
		viewHolder.mClassText = (TextView)view.findViewById(R.id.running_task_cls_name);
		return viewHolder;
	}

	@Override
	protected void setContentsToViewHolder(View view, int position) {
		RunningTaskListViewHolder viewHolder = (RunningTaskListViewHolder)view.getTag();
		ApplicationInfo appInfo = null;
		String pkgName = mInfoList.get(position).topActivity.getPackageName();
		
		try {
			if(pkgName != null){
				//Package nameからApplicationInfo objectを取得
				appInfo = mPackageMgr.getApplicationInfo(pkgName, 0);
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		
		if(appInfo != null){
			//ApplicationInfoからapplication iconを取得
			Drawable appIcon = appInfo.loadIcon(mPackageMgr);
			viewHolder.mImage.setImageDrawable(appIcon);
			//ApplicationInfoからapplication nameを取得
			String appName = (String) appInfo.loadLabel(mPackageMgr);
			viewHolder.mApplicationText.setText("Application: " + appName);
		}
		//ComponentName objectからPackage nameを取得
		viewHolder.mPackageText.setText("Package: " + pkgName);
		//ComponentName objectからClass nameを取得
		viewHolder.mClassText.setText("Class: " + mInfoList.get(position).topActivity.getClassName());
	}
	
	public static class RunningTaskListViewHolder implements ViewHolder{
		public ImageView mImage;
		public TextView mApplicationText;
		public TextView mPackageText;
		public TextView mClassText;
	}
	
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		String pkgName = mInfoList.get(position).topActivity.getPackageName();
		//PackageManagerを使いApplicationをlaunchする為のIntentを取得
		Intent intent = mPackageMgr.getLaunchIntentForPackage(pkgName);
		if(intent == null){
			Log.d(TAG, "intent null");
			return;
		}
		mContext.startActivity(intent);
	}
}

と、まあこんな感じです。他にもあるIntentに反応するpackageを取得したりとPackageManagerを使用すると色んなことが出来ます

HashTag #Java, #Android, #PackageManager, #ListView, #BaseAdapter, #RunningAppProcessInfo, #RecentTaskInfo, #RunningTaskInfo, #AdapterView.OnItemClickListener