一開始我以為,只要是支持JSR75的手機都可以支持手機內所有文件的訪問,可是在真機上一看才知道,手機的文件或者文件夾有公有與有私有之分,我們看上去像是公有的文件夾,在JAVAME里面卻不能訪問.比如我測試用的手機是諾基亞的N76,它的SD卡上的Music目錄,對于程序來說,就是私有的,不能訪問的,而"手機動漫"這個目錄卻是能訪問的.難怪我測了很多次放在Music目錄里面的歌曲,怎么播也播不出來,后來經過一步一步的調試,才知道原來此目錄下面的文件不可讀.要知道ME的調試是多么不方便,又不能用System.out.println調試,因為在真機上面根本就沒有輸出窗口.只能自己一句一句用Alert來調試.
不說廢話了,先給出代碼吧.這是一個繼承自 List的組件.用列表的方式顯示出當前目錄下的所有文件.本來是想全新寫一個的,后來發現netbeans有一個,所以就直接用了它的,寫得很不錯,說到這里,我覺得netbeans很多地方確實不錯,只是很多人由于以前的偏見沒有給它機會而已.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.hadeslee.test;
import java.io.IOException;
import java.util.Enumeration;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
/**
*
* @author hadeslee
*/
public class FileBrowser extends List implements CommandListener {
/**
* Command fired on file selection.
*/
public static final Command SELECT_FILE_COMMAND = new Command("選擇", Command.OK, 1);
private String currDirName;
private String currFile;
private Image dirIcon;
private Image fileIcon;
private CommandListener commandListener;
/* special string denotes upper directory */
private static final String UP_DIRECTORY = "..";
/* special string that denotes upper directory accessible by this browser.
* this virtual directory contains all roots.
*/
private static final String MEGA_ROOT = "/";
/* separator string as defined by FC specification */
private static final String SEP_STR = "/";
/* separator character as defined by FC specification */
private static final char SEP = '/';
private Display display;
private String selectedURL;
private String filter = null;
private String title;
/**
* Creates a new instance of FileBrowser for given <code>Display</code> object.
* @param display non null display object.
*/
public FileBrowser(Display display) {
super("文件瀏覽器", IMPLICIT);
currDirName = MEGA_ROOT;
this.display = display;
super.setCommandListener(this);
setSelectCommand(SELECT_FILE_COMMAND);
try {
dirIcon = Image.createImage(this.getClass().getResourceAsStream("dir.png"));
} catch (IOException e) {
dirIcon = null;
}
try {
fileIcon = Image.createImage(this.getClass().getResourceAsStream("file.png"));
} catch (IOException e) {
fileIcon = null;
}
showDir();
}
/**
* 顯示當前的文件夾
*/
private void showDir() {
new Thread(new Runnable() {
public void run() {
try {
showCurrDir();
} catch (SecurityException e) {
Alert alert = new Alert("錯誤", "您沒有權限訪問此文件或文件夾!", null, AlertType.ERROR);
alert.setTimeout(2000);
display.setCurrent(alert, FileBrowser.this);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* Indicates that a command event has occurred on Displayable d.
* @param c a <code>Command</code> object identifying the command. This is either
* one of the applications have been added to <code>Displayable</code> with <code>addCommand(Command)</code>
* or is the implicit <code>SELECT_COMMAND</code> of List.
* @param d the <code>Displayable</code> on which this event has occurred
*/
public void commandAction(Command c, Displayable d) {
if (c.equals(SELECT_FILE_COMMAND)) {
List curr = (List) d;
currFile = curr.getString(curr.getSelectedIndex());
new Thread(new Runnable() {
public void run() {
if (currFile.endsWith(SEP_STR) || currFile.equals(UP_DIRECTORY)) {
openDir(currFile);
} else {
//switch To Next
doDismiss();
}
}
}).start();
} else {
if (commandListener != null) {
commandListener.commandAction(c, d);
}
}
}
/**
* Sets component's title.
* @param title component's title.
*/
public void setTitle(String title) {
this.title = title;
super.setTitle(title);
}
/**
* Show file list in the current directory .
*/
private void showCurrDir() {
if (title == null) {
super.setTitle(currDirName);
}
Enumeration e = null;
FileConnection currDir = null;
deleteAll();
if (MEGA_ROOT.equals(currDirName)) {
append(UP_DIRECTORY, dirIcon);
e = FileSystemRegistry.listRoots();
} else {
try {
currDir = (FileConnection) Connector.open("file:///" + currDirName);
e = currDir.list();
} catch (IOException ioe) {
}
append(UP_DIRECTORY, dirIcon);
}
if (e == null) {
try {
currDir.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return;
}
while (e.hasMoreElements()) {
String fileName = (String) e.nextElement();
if (fileName.charAt(fileName.length() - 1) == SEP) {
// This is directory
append(fileName, dirIcon);
} else {
// this is regular file
if (filter == null || fileName.indexOf(filter) > -1) {
append(fileName, fileIcon);
}
}
}
if (currDir != null) {
try {
currDir.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
private void openDir(String fileName) {
/* In case of directory just change the current directory
* and show it
*/
if (currDirName.equals(MEGA_ROOT)) {
if (fileName.equals(UP_DIRECTORY)) {
// can not go up from MEGA_ROOT
return;
}
currDirName = fileName;
} else if (fileName.equals(UP_DIRECTORY)) {
// Go up one directory
// TODO use setFileConnection when implemented
int i = currDirName.lastIndexOf(SEP, currDirName.length() - 2);
if (i != -1) {
currDirName = currDirName.substring(0, i + 1);
} else {
currDirName = MEGA_ROOT;
}
} else {
currDirName = currDirName + fileName;
}
showDir();
}
/**
* Returns selected file as a <code>FileConnection</code> object.
* @return non null <code>FileConection</code> object
*/
public FileConnection getSelectedFile() throws IOException {
FileConnection fileConnection = (FileConnection) Connector.open(selectedURL);
return fileConnection;
}
/**
* Returns selected <code>FileURL</code> object.
* @return non null <code>FileURL</code> object
*/
public String getSelectedFileURL() {
return selectedURL;
}
/**
* Sets the file filter.
* @param filter file filter String object
*/
public void setFilter(String filter) {
this.filter = filter;
}
/**
* Returns command listener.
* @return non null <code>CommandListener</code> object
*/
protected CommandListener getCommandListener() {
return commandListener;
}
/**
* Sets command listener to this component.
* @param commandListener <code>CommandListener</code> to be used
*/
public void setCommandListener(CommandListener commandListener) {
this.commandListener = commandListener;
}
private void doDismiss() {
selectedURL = "file:///" + currDirName + currFile;
CommandListener listener = getCommandListener();
if (listener != null) {
listener.commandAction(SELECT_FILE_COMMAND, this);
}
}
}
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.hadeslee.test;
import java.io.IOException;
import java.util.Enumeration;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
/**
*
* @author hadeslee
*/
public class FileBrowser extends List implements CommandListener {
/**
* Command fired on file selection.
*/
public static final Command SELECT_FILE_COMMAND = new Command("選擇", Command.OK, 1);
private String currDirName;
private String currFile;
private Image dirIcon;
private Image fileIcon;
private CommandListener commandListener;
/* special string denotes upper directory */
private static final String UP_DIRECTORY = "..";
/* special string that denotes upper directory accessible by this browser.
* this virtual directory contains all roots.
*/
private static final String MEGA_ROOT = "/";
/* separator string as defined by FC specification */
private static final String SEP_STR = "/";
/* separator character as defined by FC specification */
private static final char SEP = '/';
private Display display;
private String selectedURL;
private String filter = null;
private String title;
/**
* Creates a new instance of FileBrowser for given <code>Display</code> object.
* @param display non null display object.
*/
public FileBrowser(Display display) {
super("文件瀏覽器", IMPLICIT);
currDirName = MEGA_ROOT;
this.display = display;
super.setCommandListener(this);
setSelectCommand(SELECT_FILE_COMMAND);
try {
dirIcon = Image.createImage(this.getClass().getResourceAsStream("dir.png"));
} catch (IOException e) {
dirIcon = null;
}
try {
fileIcon = Image.createImage(this.getClass().getResourceAsStream("file.png"));
} catch (IOException e) {
fileIcon = null;
}
showDir();
}
/**
* 顯示當前的文件夾
*/
private void showDir() {
new Thread(new Runnable() {
public void run() {
try {
showCurrDir();
} catch (SecurityException e) {
Alert alert = new Alert("錯誤", "您沒有權限訪問此文件或文件夾!", null, AlertType.ERROR);
alert.setTimeout(2000);
display.setCurrent(alert, FileBrowser.this);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* Indicates that a command event has occurred on Displayable d.
* @param c a <code>Command</code> object identifying the command. This is either
* one of the applications have been added to <code>Displayable</code> with <code>addCommand(Command)</code>
* or is the implicit <code>SELECT_COMMAND</code> of List.
* @param d the <code>Displayable</code> on which this event has occurred
*/
public void commandAction(Command c, Displayable d) {
if (c.equals(SELECT_FILE_COMMAND)) {
List curr = (List) d;
currFile = curr.getString(curr.getSelectedIndex());
new Thread(new Runnable() {
public void run() {
if (currFile.endsWith(SEP_STR) || currFile.equals(UP_DIRECTORY)) {
openDir(currFile);
} else {
//switch To Next
doDismiss();
}
}
}).start();
} else {
if (commandListener != null) {
commandListener.commandAction(c, d);
}
}
}
/**
* Sets component's title.
* @param title component's title.
*/
public void setTitle(String title) {
this.title = title;
super.setTitle(title);
}
/**
* Show file list in the current directory .
*/
private void showCurrDir() {
if (title == null) {
super.setTitle(currDirName);
}
Enumeration e = null;
FileConnection currDir = null;
deleteAll();
if (MEGA_ROOT.equals(currDirName)) {
append(UP_DIRECTORY, dirIcon);
e = FileSystemRegistry.listRoots();
} else {
try {
currDir = (FileConnection) Connector.open("file:///" + currDirName);
e = currDir.list();
} catch (IOException ioe) {
}
append(UP_DIRECTORY, dirIcon);
}
if (e == null) {
try {
currDir.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return;
}
while (e.hasMoreElements()) {
String fileName = (String) e.nextElement();
if (fileName.charAt(fileName.length() - 1) == SEP) {
// This is directory
append(fileName, dirIcon);
} else {
// this is regular file
if (filter == null || fileName.indexOf(filter) > -1) {
append(fileName, fileIcon);
}
}
}
if (currDir != null) {
try {
currDir.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
private void openDir(String fileName) {
/* In case of directory just change the current directory
* and show it
*/
if (currDirName.equals(MEGA_ROOT)) {
if (fileName.equals(UP_DIRECTORY)) {
// can not go up from MEGA_ROOT
return;
}
currDirName = fileName;
} else if (fileName.equals(UP_DIRECTORY)) {
// Go up one directory
// TODO use setFileConnection when implemented
int i = currDirName.lastIndexOf(SEP, currDirName.length() - 2);
if (i != -1) {
currDirName = currDirName.substring(0, i + 1);
} else {
currDirName = MEGA_ROOT;
}
} else {
currDirName = currDirName + fileName;
}
showDir();
}
/**
* Returns selected file as a <code>FileConnection</code> object.
* @return non null <code>FileConection</code> object
*/
public FileConnection getSelectedFile() throws IOException {
FileConnection fileConnection = (FileConnection) Connector.open(selectedURL);
return fileConnection;
}
/**
* Returns selected <code>FileURL</code> object.
* @return non null <code>FileURL</code> object
*/
public String getSelectedFileURL() {
return selectedURL;
}
/**
* Sets the file filter.
* @param filter file filter String object
*/
public void setFilter(String filter) {
this.filter = filter;
}
/**
* Returns command listener.
* @return non null <code>CommandListener</code> object
*/
protected CommandListener getCommandListener() {
return commandListener;
}
/**
* Sets command listener to this component.
* @param commandListener <code>CommandListener</code> to be used
*/
public void setCommandListener(CommandListener commandListener) {
this.commandListener = commandListener;
}
private void doDismiss() {
selectedURL = "file:///" + currDirName + currFile;
CommandListener listener = getCommandListener();
if (listener != null) {
listener.commandAction(SELECT_FILE_COMMAND, this);
}
}
}
這個類可以用做瀏覽手機文件之用,也可以用做得到得選的文件之用,如果想要在選擇了文件以后做什么事情的話,可以調用它的setCommandListener方法.并且處理SELECT_FILE_COMMAND.
經過試驗,我發現所有的只讀文件夾對于FileConnection來說,就是私有的,是不能訪問到的,所以當我們要訪問的時候,最好是把那些只讀的文件夾改為可讀寫.
發現一件N76的文件的好玩的事情.在N76里面,你訪問的時候,總共有四個根文件夾,分別是:
手機存儲/ C:/ 存儲卡/ E:/
可是我發現手機存儲和C是一樣的,存儲卡和E也是一樣的,也就是說可以用file:///手機存儲/來訪問也可以用file:///C:/來訪問.
盡管千里冰封
依然擁有晴空
你我共同品味JAVA的濃香.