2011年05月14日

最近はまったこと その1(アプリケーション一覧を取得)

Android端末にインストールされているアプリケーション一覧を取得し、カスタマイズされたリストへ表示しようとしました。
長くなりますが、今回はソース全文から。(お試しで作っているのでアプリケーション名は適当です)


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<ListView
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:id="@+id/CustListView"
    />
</LinearLayout>


lixt_item.xml(カスタムリスト表示用)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <ImageView
  android:layout_width="60dip"
  android:layout_height="60dip"
  android:id="@+id/image"
  />
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content">
 <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:padding="5dip"
  android:id="@+id/name"
  android:textStyle="bold"
  android:scrollHorizontally="true"
  android:textSize="20dip"
  android:layout_gravity="center_vertical"
  />
</LinearLayout>
</LinearLayout>


アプリケーションコード本体
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class OnlyOne extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        PackageManager pm = getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN,null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);

        final List<ResolveInfo> appList = pm.queryIntentActivities(intent, 0);
        Collections.sort(appList,new ResolveInfo.DisplayNameComparator(pm));

        List<ListItem> list = new ArrayList<ListItem>();

//ListItem listItem = new ListItem(); // 誤

        for(ResolveInfo resolveInfo : appList){
            ListItem listItem = new ListItem(); // 正
        listItem.setName(resolveInfo.loadLabel(pm).toString());
        listItem.setImage(resolveInfo.loadIcon(pm));
        list.add(listItem);
        }

        ListItemAdapter adapter = new ListItemAdapter(this,0,list);

        ListView listView = (ListView)findViewById(R.id.CustListView);
        listView.setAdapter(adapter);

    }

    class ListItem{
    //private int imageId;
    private Drawable draw;
    private String appName;

    public Drawable getImage(){
    return draw;
    }
    public void setImage(Drawable draw){
    this.draw = draw;
    }
    public String getName(){
    return appName;
    }
    public void setName(String appName){
    this.appName = appName;
    }
    }

    public class ListItemAdapter extends ArrayAdapter<ListItem> {
    private LayoutInflater mInflater;

    public ListItemAdapter(Context context,int rid,List<ListItem> custList){
    super(context,rid,custList);
    mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public View getView(int position,View convertView,ViewGroup parent){

    if(convertView == null){
    convertView = mInflater.inflate(R.layout.list_item, null);
    }
    //データを取り出す
    ListItem item = (ListItem)getItem(position);

    //画像をセット
    ImageView image = (ImageView)convertView.findViewById(R.id.image);
    image.setImageDrawable(item.getImage());

    //アプリ名をセット
    TextView name = (TextView)convertView.findViewById(R.id.name);
    name.setText(item.getName());

    return convertView;
    }
    }

}

ListItemを生成している辺りの拡張for文前後のコメントで//正、//誤と書かれたところを見ていただければ分かると思いますが、変な位置でカスタム化リスト(ListItem)のインスタンスを生成しているので、何度やってもソートされたリスト上最後に来るアプリ名がアプリケーション数だけ繰り返しリストに表示され、同じ名前ばかりが表示されるという現象が発生していたのです。
前にリストのカスタマイズはやったことがあるので、その時のコードと照らし合わせてみて、どうして思ったように動かないのだろうと延々と悩みましたが、考えてみると同じインスタンスを何度も参照することになるので当たり前と言えば当たり前ですね。
通常のfor文だったらもう少し早く気づいていたかも知れませんが、慣れない拡張for文のため見過ごしていたようです。(負け惜しみ(笑))
一応これで動きましたが、なんだか不安定な気も……というかテストに使っている端末が急に調子が悪くなったので、そのせいかも知れませんが、メソッドを正しく理解しながら書いている訳ではないので、その辺りが「プラグラマー」の悲しいところです。

posted by 白虹 at 23:32| Comment(0) | TrackBack(0) | Android開発