package talent.fm;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class FileView extends ListView{
private FileAdapter browser;
public interface OnPathChanged{
abstract boolean onChanged(String old,String path);
}
public void SetOnPathChangedListener(OnPathChanged listener){
if(browser==null) return;
browser.onChanged = listener;
}
public FileView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public FileView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.FileView);
String path = a.getString(R.styleable.FileView_path);
a.recycle();
if(path!=null)
browser.SetPath(path);
}
public FileView(Context context) {
super(context);
init();
}
private void init(){
browser = new FileAdapter();
setAdapter(browser);
setOnItemClickListener(onItemClick);
}
private OnItemClickListener onItemClick = new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
//com.Logi("item:"+arg2);
if(!browser.OpenChild(arg2)){
com.Toast(arg1.getContext(),"folder is empty or can't open");
return;
}
}
};
/**goto parent folder,return false if no parent folder.*/
public boolean Up(){
return browser.Up();
}
public void SetPath(String path){
browser.SetPath(path);
}
public String GetPath(){
return browser.GetPath();
}
}
class FileAdapter extends BaseAdapter{
private String path = "/";
private List<FileInfo> contents = new ArrayList<FileInfo>();
protected FileView.OnPathChanged onChanged;
Console cs = new Console();
private final static int BROWS_MODE_SU = 1,
BROWS_MODE_APK = 2;
private int mode = BROWS_MODE_SU;
private class FileInfo{
String Name;
int IconId;
FileInfo(String name,int id){
Name = name;
IconId = id;
}
boolean IsFolder(){
return R.drawable.icon_folder==IconId;
}
}
public boolean SetSUMode(){
mode = BROWS_MODE_SU;
return true;
}
public void SetAPKMode(){
mode = BROWS_MODE_APK;
SetPath(path);
}
public FileAdapter(){
cs.SetOnOutput(onConsoleOutput);
if(!cs.Create())
SetAPKMode();
}
@Override
public int getCount() {
return contents.size();
}
/**return a File Object*/
@Override
public Object getItem(int position) {
if(position>=contents.size()) return null;
return contents.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.item_explorer,null);
}
FileInfo fi = contents.get(position);
ImageView iv = (ImageView)convertView.findViewById(R.id.explorer_iv_image);
iv.setImageResource(fi.IconId);
TextView tv = (TextView)convertView.findViewById(R.id.explorer_iv_text);
tv.setText(fi.Name);
return convertView;
}
public void SetPath(String path){
com.Logi(path);
if(path==null||path.length()==0)
path = "/";
contents.clear();
notifyDataSetChanged();
if(onChanged!=null) onChanged.onChanged(this.path,path);
this.path = path;
if(this.mode==BROWS_MODE_APK){
File file = new File(path);
String[] fnl = file.list();
com.Logw("fnl:"+fnl);
File[] fl = file.listFiles();
if(fl==null){
com.Loge("init path:"+path);
return;
}
Arrays.sort(fl);
folderInsertPos = 0;
for(int i=0;i<fl.length;i++){
insertByFile(fl[i]);
}
notifyDataSetChanged();
}else if(mode==BROWS_MODE_SU){
String cmd = "ls " + path;
if(!cs.Exec(cmd))
SetAPKMode();
}
}
public String GetPath(){
return path;
}
public boolean OpenChild(int index){
if(index<0||index>=contents.size()) return false;
FileInfo fi = contents.get(index);
if(!fi.IsFolder()) return false;
if(path.equals("/")) path = "";
SetPath(path+"/"+fi.Name);
return true;
}
public boolean Up(){
File file = new File(path);
File root = file.getParentFile();
if(root==null) return false;
SetPath(root.getPath());
return true;
}
private Console.OnOutput onConsoleOutput = new Console.OnOutput(){
@Override
public void onOutput(String str) {
Message msg = new Message();
msg.what = MSG_NOTIFY_STR;
Bundle bundle = new Bundle();
bundle.putString("output_str",str);
msg.setData(bundle);
notifyHandler.sendMessage(msg);
}
};
private int folderInsertPos = 0;
/**insert FileInfo object in contents set,and position by name*/
private void insertByName(String str){
String fp = path + "/" + str;
File file = new File(fp);
insertByFile(file);
}
private void insertByFile(File file){
int icon;
if(file.isDirectory()){
icon = R.drawable.icon_folder;
contents.add(folderInsertPos,new FileInfo(file.getName(),icon));
folderInsertPos++;
}
else{
if(file.isFile()){
icon = R.drawable.icon_file;
}
else{
icon = R.drawable.icon_script;
}
contents.add(new FileInfo(file.getName(),icon));
}
}
private final static int MSG_NOTIFY_DATA = 1,
MSG_NOTIFY_STR = 2;
private Handler notifyHandler = new Handler(){
@Override
public void handleMessage(Message msg){
if(msg.what==MSG_NOTIFY_STR){
String str = msg.getData().getString("output_str");
if(str.length()==0) return;
String[] fns = str.split("\\|");
Arrays.sort(fns);
folderInsertPos = 0;
for(int i=0;i<fns.length;i++){
insertByName(fns[i]);
}
notifyDataSetChanged();
}else if(msg.what==MSG_NOTIFY_DATA){
}
}
};
}
package talent.fm;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class Console{
private boolean notExit = true;
private ReadThread readTh = new ReadThread();
private DataInputStream input;
private DataOutputStream output;
private OnOutput onOutput;
public interface OnOutput{
void onOutput(String str);
}
/**must call this function or thread will not terminate*/
public void Close(){
notExit = false;
if(input!=null){
try {
input.close();
} catch (IOException e) {
com.Loge("Console.Close input:"+e.getMessage());
}
}
}
public boolean Create(){
// Root android su
Process process;
try {
process = Runtime.getRuntime().exec("su ");
} catch (IOException e) {
com.Loge("Console.Create:"+e.getMessage());
return false;
} catch (SecurityException e){
com.Loge("Console.Create:"+e.getMessage());
return false;
}
output = new DataOutputStream(process.getOutputStream());
input = new DataInputStream(process.getInputStream());
readTh.start();
return true;
}
public boolean Exec(String cmd){
try {
output.writeBytes(cmd+"
");
output.flush();
return true;
} catch (IOException e) {
com.Loge("Console.Exec:"+e.getMessage());
}
return false;
}
class ReadThread extends Thread{
@Override
public void run() {
String outstr = "";
while(notExit){
try {
int len = input.available();
if(0==len){
if(onOutput!=null) onOutput.onOutput(outstr);
outstr = "";
}
String str = input.readLine();
if(str==null) break;
outstr += str + "|";
} catch (IOException e) {
com.Loge("Console.Thread.run:"+e.getMessage());
break;
}
}
}
}
public void SetOnOutput(OnOutput opt) {
onOutput = opt;
}
}