端末内のファイル、フォルダを探索するアプリを作る時、Handler を使えば、
Activity 1つで構成できる。
こんな画面を作るケース、
まずは、XMLレイアウト、
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/currentPathTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:text="Medium Text"
android:background="#ffffff"
android:textColor="#000000"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp" >
<Button
android:id="@+id/backButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="BACK" />
</LinearLayout>
</LinearLayout>
1行のレイアウトは、ここでは省略
Activity は、以下のとおり。。。
public class SdCardExplorerActivity extends Activity{
TextView mCurrentPathTextView;
ListView mListView;
List<File> mFileList;
Stack<String> mHistory;
String mRootPath;
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
String path = msg.obj.toString();
removeMessages(0);
mCurrentPathTextView.setText(path);
mFileList.clear();
if (path.equals(mRootPath)==false) mFileList.add(new File(path+"/../"));
for(File file : new File(path).listFiles()){
mFileList.add(file);
}
*1.notifyDataSetChanged();
}
};
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setSoftInputMode(
android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);
setContentView(R.layout.sd_explorer);
mFileList = new ArrayList<File>();
mHistory = new Stack<String>();
mCurrentPathTextView = (TextView)findViewById(R.id.currentPathTextView);
mListView = (ListView)findViewById(R.id.listView);
mListView.setAdapter(new BaseAdapter(){
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@Override
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView==null ? inflater.inflate(R.layout.directory_row, null) : convertView;
final File file = mFileList.get(position);
ImageView imageView = (ImageView)view.findViewById(R.id.imageView);
imageView.setImageResource(file.isDirectory() ? R.drawable.ic_menu_folder : R.drawable.ic_menu_file);
final TextView textView = (TextView)view.findViewById(R.id.fileTextView);
textView.setText(file.getName());
try{
textView.setTextColor(ColorStateList.createFromXml(getResources(), getResources().getXml(R.color.text_selector)));
}catch(Exception e){
Log.e("sample",e.getMessage(),e);
}
view.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
textView.setSelected(false);
if (file.isDirectory()){
if (file.canRead()){
String path = file.getAbsolutePath();
if (path.endsWith("/..")){
path = file.getParentFile().getParent();
}
mHistory.add(mCurrentPathTextView.getText().toString());
Message message = Message.obtain();
message.obj = path;
mHandler.sendMessage(message);
}else{
Toast.makeText(getApplicationContext(),"読込み権限がありません",Toast.LENGTH_SHORT).show();
}
}
}
});
view.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event){
int action = event.getAction();
if (action==MotionEvent.ACTION_DOWN || action==MotionEvent.ACTION_MOVE){
textView.setSelected(true);
}else{
textView.setSelected(false);
}
return false;
}
});
view.setBackgroundResource(R.color.list_selector);
return view;
}
@Override
public long getItemId(int position){
return position;
}
@Override
public Object getItem(int position){
return mFileList.get(position);
}
@Override
public int getCount(){
return mFileList.size();
}
});
*2.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if (mHistory.isEmpty()){
finish();
}else{
Message message = Message.obtain();
message.obj = mHistory.pop();
mHandler.sendMessage(message);
}
}
});
}
@Override
protected void onResume(){
super.onResume();
String sdPath = getSdPath();
if (sdPath != null){
mRootPath = sdPath;
mCurrentPathTextView.setText(sdPath);
for(File f : new File(sdPath).listFiles()){
mFileList.add(f);
}
*3.notifyDataSetChanged();
}else{
new AlertDialog.Builder(this).setTitle("Error").setIcon(android.R.drawable.ic_dialog_alert)
.setMessage("SD card No found!").setPositiveButton("OK",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog,int which){
}
}).create().show();
}
}
/* @see android.app.Activity#dispatchKeyEvent(android.view.KeyEvent) */
@Override
public boolean dispatchKeyEvent(KeyEvent event){
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK && event.getAction()==KeyEvent.ACTION_DOWN){
if (mHistory.isEmpty()){
finish();
}else{
Message message = Message.obtain();
message.obj = mHistory.pop();
mHandler.sendMessage(message);
}
return true;
}
return super.dispatchKeyEvent(event);
}
/*
* SDカード path、mount されてなければ、null を返す
*/
private String getSdPath(){
File f = new File(System.getenv("EXTERNAL_STORAGE"));
if (!f.exists()) return null;
if (!f.isDirectory()) return null;
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return null;
try{
if (f.listFiles().length > 0){
return f.getAbsolutePath();
}
}catch(Throwable e){
Log.e("sample",e.getMessage(),e);
}
return null;
}
}