ついでにActivityManager - 実行中のProcessやTask、最近起動したTask情報取得

はい、連日のpostになります。Managerしばりということで今回はActivityManagerです。下のScreen shotはRecentTask情報になります(Home button長押しすると出てくる奴と同じ情報)


ActivityManagerとは

Systemで動作しているProcessやTaskの情報を取得することが出来ます。BackgroundにあるProcessを殺したり、Foregroundに持ってきたりする事も出来ます

実装の要点は下記です(特にそんなにないけど)

  1. Task情報取得のためにAndroidManifest.xmlandroid.permission.GET_TASKSを記載(必要であればKILL_BACKGROUND_PROCESSESやREORDER_TASKを記載)
  2. ActivityManager objectを取得
  3. RunningAppProcessInfo, RecentTaskInfo, RunningTaskInfo等各種情報を取得

気付いた点をまとめます

  • ActivityManager#killBackgroundProcesses()を実行してもRunningTaskInfoからは消えない。SystemによりProcessは殺されているが、Userが戻ってくる時の為に最終的な状態を保持しているということがあるそうで、その際はRunningTaskInfoとして保持されるようです。(良くわかりませんが詳しくはRunningTaskInfoの説明を読んで下さい)
  • Process nameとPackage nameは基本一緒

んで実装です

AndroidManifest.xml

<?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) {
		BaseAdapter adapter = null;
		String title = null;
		switch(v.getId()){
		case R.id.process_display_button:
			adapter = new ProcessAdapter(this);
			title = "Process";
			break;
		case R.id.recent_task_display_button:
			adapter = new RecentTaskAdapter(this);
			title = "Recent Task";
			break;
		case R.id.running_task_display_button:
			adapter = new RunningTaskAdapter(this);
			title = "Running Task";
			break;
		default:
			return;
		}
		
		showListDialog(this, adapter, title);
	}
	
	private void showListDialog(Context context, BaseAdapter adapter, String title){
		final ListView lv = new ListView(context);
		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();
	}
}

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.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;
	protected List<T> mInfoList;
	
	public AbsActivityManagerAdapter(Context context){
		mContext = context;
		//ActivityManager objectを取得
		mActivityMgr = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
		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.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class ProcessAdapter extends AbsActivityManagerAdapter<RunningAppProcessInfo> {

	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.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();
		//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 TextView mProcessText;
		public TextView mImportanceText;
		public TextView mImportanceReasonText;
	}
}

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.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class RecentTaskAdapter extends AbsActivityManagerAdapter<RecentTaskInfo>{

	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.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();
		//Taskを起動したIntentを取得
		Intent intent =  mInfoList.get(position).baseIntent;
		//ComponentName objectからPackageNameを取得
		viewHolder.mPackageText.setText("Package: " + intent.getComponent().getPackageName());
	}
	
	public static class RecentTaskListViewHolder implements ViewHolder{
		public TextView mPackageText;
	}
}

RunningTaskInfo取得class

package com.android.practice;

import java.util.List;

import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class RunningTaskAdapter extends AbsActivityManagerAdapter<RunningTaskInfo>{

	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.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();
		//ComponentName objectからPackage nameを取得
		viewHolder.mPackageText.setText("Package: " + mInfoList.get(position).topActivity.getPackageName());
		//ComponentName objectからClass nameを取得
		viewHolder.mClassText.setText("Class: " + mInfoList.get(position).topActivity.getClassName());
	}
	
	public static class RunningTaskListViewHolder implements ViewHolder{
		public TextView mPackageText;
		public TextView mClassText;
	}
}

こんな感じです。今回は情報を取得してDialogのListViewで表示しているだけですが、次回はPostの際にはPackageManagerを扱いとそれと連携させてAppの起動等が出来れば良いかなと思います

HashTag #Java, #Android, #ActivityManager, #RunningAppProcessInfo, #RecentTaskInfo, #RunningTaskInfo, #Dialog, #BaseAdaper, #ListView, #ViewHolder