1 package org.easyrpg.player; 2 3 import java.io.File; 4 import java.io.FilenameFilter; 5 import java.util.ArrayList; 6 import java.util.Arrays; 7 import java.util.LinkedList; 8 import java.util.List; 9 import java.util.Map; 10 import java.util.Set; 11 12 import android.app.AlertDialog; 13 import android.content.Context; 14 import android.content.DialogInterface; 15 import android.content.DialogInterface.OnClickListener; 16 import android.util.Log; 17 import android.view.View; 18 import android.widget.AdapterView; 19 import android.widget.ArrayAdapter; 20 import android.widget.Button; 21 import android.widget.EditText; 22 import android.widget.ListView; 23 import android.widget.Toast; 24 25 26 public class DirectoryChooser { 27 private static String selected_path; 28 29 AlertDialog.Builder builder; 30 AlertDialog dialog; 31 ListView listView; 32 Context context; 33 34 LinkedList<String> currentDirPath = new LinkedList<String>(); 35 List<String> dir_list; 36 37 DirectoryChooser(final Context context, String path, final Runnable runnable)38 public DirectoryChooser(final Context context, String path, final Runnable runnable) { 39 this.context = context; 40 this.builder = new AlertDialog.Builder(context); 41 this.listView = new ListView(context); 42 43 builder.setPositiveButton(R.string.ok, null); 44 builder.setNeutralButton(R.string.quick_access, null); 45 builder.setView(listView); 46 47 // Current directory 48 if (path != null) { 49 currentDirPath.addAll(Arrays.asList(path.split("/"))); 50 } 51 52 //Display the folder's list first 53 dialog = builder.create(); 54 displayItemList(); 55 56 // Set up action to button (after the dialog creation to avoid automatic closing) 57 // (Android "logic") 58 dialog.setOnShowListener(new DialogInterface.OnShowListener() { 59 @Override 60 public void onShow(DialogInterface d) { 61 //OK's button 62 Button b = dialog.getButton(AlertDialog.BUTTON_POSITIVE); 63 b.setOnClickListener(new View.OnClickListener() { 64 @Override 65 public void onClick(View view) { 66 selected_path = dirListToPath(currentDirPath); 67 runnable.run(); 68 69 // Dismiss once everything is OK. 70 dialog.dismiss(); 71 } 72 }); 73 74 //Create Quick access button 75 Button b2 = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); 76 b2.setOnClickListener(new View.OnClickListener() { 77 @Override 78 public void onClick(View view) { 79 quickAccess(); 80 } 81 }); 82 } 83 }); 84 85 dialog.show(); 86 } 87 quickAccess()88 public void quickAccess() { 89 final ListView lv = new ListView(context); 90 91 AlertDialog.Builder builder = new AlertDialog.Builder(context); 92 builder 93 .setTitle(R.string.quick_access) 94 .setView(lv) 95 .setCancelable(true); 96 97 final AlertDialog quickDialog = builder.create(); 98 99 final Map<String, File> allLocations = ExternalStorage.getAllStorageLocations(); 100 final String[] keySet = allLocations.keySet().toArray(new String[allLocations.size()]); 101 lv.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, keySet)); 102 103 // When clicking on an item, the list display the new path 104 lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { 105 106 public void onItemClick(AdapterView<?> arg0, View view, int pos, long id) { 107 String newPath = allLocations.get(keySet[pos]).getAbsolutePath(); 108 109 if (isReadable(newPath)) { 110 currentDirPath.clear(); 111 currentDirPath.addAll(Arrays.asList(newPath.split("/"))); 112 113 displayItemList(); 114 } else { 115 String msg = context.getString(R.string.path_not_readable).replace("$PATH", newPath); 116 Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); 117 } 118 119 quickDialog.dismiss(); 120 } 121 }); 122 123 quickDialog.show(); 124 } 125 126 /** 127 * Returns the folder's list of path 128 */ listDir(String path)129 public List<String> listDir(String path) { 130 List<String> dirList = new ArrayList<String>(); 131 132 // Add the ".." item if we're not at the root 133 if (!path.equals("/")) { 134 dirList.add(".."); 135 } 136 137 // List the directories in "path" 138 File dir = new File(path); 139 String[] directories = dir.list(new FilenameFilter() { 140 @Override 141 public boolean accept(File current, String name) { 142 File newFile = new File(current, name); 143 return newFile.isDirectory() && !newFile.isHidden(); 144 } 145 }); 146 147 if (directories != null) { 148 Arrays.sort(directories); 149 dirList.addAll(new ArrayList<String>(Arrays.asList(directories))); 150 } 151 152 return dirList; 153 } 154 displayItemList()155 public void displayItemList() { 156 // Retrieve the folder's list to display 157 String path = dirListToPath(currentDirPath); 158 dir_list = listDir(path); 159 dialog.setTitle(path); 160 161 listView.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, dir_list)); 162 163 // When clicking on an item, the list display the new path 164 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 165 166 public void onItemClick(AdapterView<?> arg0, View view, int pos, long id) { 167 String dirName = dir_list.get(pos); 168 169 // Updating the current directory 170 if (dirName.equals("..")) { 171 currentDirPath.removeLast(); 172 } else { 173 String newPath = dirListToPath(currentDirPath) + "/" + dir_list.get(pos); 174 175 if (isReadable(newPath)) { 176 currentDirPath.add(dir_list.get(pos)); 177 } else { 178 String msg = context.getString(R.string.path_not_readable).replace("$PATH", newPath); 179 Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); 180 } 181 } 182 183 displayItemList(); 184 } 185 }); 186 } 187 dirListToPath(LinkedList<String> l)188 public static String dirListToPath(LinkedList<String> l) { 189 if (l.size() <= 1) 190 return "/"; 191 192 StringBuilder s = new StringBuilder(); 193 for (int i = 0; i < l.size(); i++) { 194 if (i > 0) { 195 s.append("/"); 196 } 197 s.append(l.get(i)); 198 } 199 200 return s.toString(); 201 } 202 isReadable(String path)203 public boolean isReadable(String path) { 204 File file = new File(path); 205 boolean canRead = file.canRead(); 206 if (!canRead) { 207 Log.e("isReadable", "Current context not allowed to read : " + path); 208 } 209 return canRead; 210 } 211 getSelectedPath()212 public static String getSelectedPath() { 213 return selected_path; 214 } 215 } 216