2010年10月14日木曜日

SDカードの中身を ListView を使って表示&選択 (拡張子フィルター付)

こんな感じのサンプル・アプリを作ってみました。

起動直後
起動直後に、/sdcard 内のディレクトリ及びファイル(拡張子が.xmlのみ)を表示します。

上記画面で、dir1 を選択すると、以下のように、/sdcard/dir1 内が表示されます

1つ下に移動し、ファイル選択
test1_1.xml を選択すると、EditText にフルパス名が自動セットされ、
最下段にある OK ボタンが Enable になります。

/sdcard 直下では表示されませんが、
/sdcard/dir1 など、/sdcard のサブ・ディレクトリでは上位ディレクトリに戻るために、
"...(上へ)" を表示&選択できるようにしています。

ちなみに、SDカードへの書き込みを行う際は、AndroidManifest.xml に、
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
を記述する必要があります。


以下はソースです。

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"
    >

<TextView
    android:id="@+id/current_dir"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

<ListView
    android:id="@+id/select_file"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="2"
/>

<TextView
    android:text="ファイル名:"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

<EditText
    android:id="@+id/file_text"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />

<Button
    android:id="@+id/ok_button"
    android:text="OK"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    />

</LinearLayout>



SdCardDisplayActivity.java
package jp.kochi;

import java.io.File;
import java.io.FileFilter;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class SdCardDisplayActivity extends Activity implements OnItemClickListener {

    private ListView mListView;
    private EditText mEditText;
    private TextView mCurDirTextView;
    private File mFile;
    private String mWarning;
    private String mGoUp;
    private File mSDdir;
    private Button mButton;

      @Override
      public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

          setContentView(R.layout.main);

          mCurDirTextView = (TextView) findViewById(R.id.current_dir);
          mButton = (Button) findViewById(R.id.ok_button);
          mButton.setEnabled(false);

      mWarning = "警告";
      mGoUp    = ".. (上へ)";

          //final File SDdir
          mSDdir = Environment.getExternalStorageDirectory();
      Log.v("DEBUG", "getExternalStorageDirectory() = " + mSDdir.getPath());

          String SDstatus = Environment.getExternalStorageState();
      Log.v("DEBUG", "getExternalStorageState() = " + SDstatus);

      // SDカードがセットされているか確認
      if (SDstatus.equals(Environment.MEDIA_MOUNTED) == false &&
          SDstatus.equals(Environment.MEDIA_MOUNTED_READ_ONLY) == false) {

        AlertDialog.Builder builder = new AlertDialog.Builder(SdCardDisplayActivity.this);

        builder.setTitle(mWarning);
        builder.setMessage("SDカードがセットされていません。");
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener () {

          @Override
          public void onClick(DialogInterface dialog, int which) {
            Log.v("DEBUG", "alerDialog - OnClickListener()");
            SdCardDisplayActivity.this.finish();
          }
        });

        builder.show();

        Log.v("DEBUG", "finish: " + this.getClass().getName());

      }

          mListView = (ListView) findViewById(R.id.select_file);
          mListView.setOnItemClickListener(this);
          //list.setAdapter(new ListAdapter)
          updateList(mSDdir);

          Button select = (Button) findViewById(R.id.ok_button);
          select.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
          Toast.makeText(SdCardDisplayActivity.this, mEditText.getText(), Toast.LENGTH_LONG).show();
          // --------------------------
          // ファイル読込み等の処理を行う
          // --------------------------
        }
      });


          mEditText = (EditText) findViewById(R.id.file_text);
      }

      final private FileFilter filter = new FileFilter() {
      @Override
      public boolean accept(File pathname) {
        if (pathname.isDirectory() == true) {
          return true;
        } else if(pathname.getName().endsWith(".xml") == true){
          return true;
        }
        return false;
      }
    };

      private void updateList(File dir){

        // EditText に選択されたファイル名/フォルダ名をセット
        mCurDirTextView.setText(dir.getAbsolutePath());

        SimpleAdapter adapter = new SimpleAdapter(this, getData(dir.listFiles(filter), dir.getParentFile()),
                  android.R.layout.simple_list_item_1, new String[] { "name" },
                  new int[] { android.R.id.text1 });

        mListView.setAdapter(adapter);
      }

    private List getData(File[] files, File parent) {

      Map<String, Object> temp;
      List<Map> myData = new ArrayList<Map>();

      if (parent != null && mSDdir.getParent().equals(parent.getAbsolutePath()) == false) {
        temp = new HashMap<String, Object>();
        temp.put("name", mGoUp);
        temp.put("file", parent);
        myData.add(temp);
      }

      if (files != null) {
        for(File file : files){
          temp = new HashMap<String, Object>();
          if (file.isDirectory()) {
            temp.put("name", file.getName() + "/");
          } else {
            temp.put("name", file.getName());
          }
          temp.put("file", file);
          myData.add(temp);
        }
      }

      Collections.sort(myData, sDisplayNameComparator);

      return myData;
    }

    private final static Comparator<Map> sDisplayNameComparator = new Comparator<Map>() {
      private final Collator collator = Collator.getInstance();

      public int compare(Map map1, Map map2) {
        return collator.compare(map1.get("name"), map2.get("name"));
      }
    };

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
      Map map = (Map) arg0.getItemAtPosition(arg2);
      mFile = (File) map.get("file");

      mEditText.setText(mFile.getAbsolutePath());
      if (mFile.isDirectory()) {
        mButton.setEnabled(false);
        updateList(mFile);
      } else {
          // ファイルだったら、ボタンを押せるようにする
          mButton.setEnabled(true);
      }


    }
  }