編輯:Android開發教程
AndroidManifest.xml中manifest標簽下有一個屬性android:installLocation
,用於指定應用程序安裝在什麼地方,該屬性有三個可選值:
獲取External存儲的權限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Context提供了兩個方法打開應用程序的數據文件夾裡的文件IO流:
Context還提供了訪問應用程序的數據文件夾的方法:
核心代碼如下:
public String read() { try { FileInputStream inStream = this.openFileInput("message.txt"); byte[] buffer = new byte[1024]; int hasRead = 0; StringBuilder sb = new StringBuilder(); while ((hasRead = inStream.read(buffer)) != -1) { sb.append(new String(buffer, 0, hasRead)); } inStream.close(); return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } public void write(String msg){ // 步驟1:獲取輸入值 if(msg == null) return; try { // 步驟2:創建一個FileOutputStream對象,MODE_APPEND追加模式 FileOutputStream fos = openFileOutput("message.txt", MODE_APPEND); // 步驟3:將獲取過來的值放入文件 fos.write(msg.getBytes()); // 步驟4:關閉數據流 fos.close(); } catch (Exception e) { e.printStackTrace(); } }
openFileOutput()方法的第一參數用於指定文件名稱,不能包含路徑分隔符“/” ,如果文件不存在,Android 會自動創建它。創建的文件保存在/data/data/<package name>/files目錄,如: /data/data/cn.tony.app/files/message.txt,
讀寫SD卡上文件的步驟:
//如果返回true,說明已插入SD卡,且應用程序具有讀寫SD卡的能力
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
為了讀寫SD卡上的數據,必須在AndroidManifest.xml中添加讀寫SD卡的權限:
<!-- 在SD卡中創建於刪除文件權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 向SD卡中寫入數據權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
接著在使用SDcard進行讀寫的時候 會用到Environment類下面的幾個靜態方法 :
1: getDataDirectory() 獲取到Android中的data數據目錄(sd卡中的data文件夾)
2:getDownloadCacheDirectory() 獲取到下載的緩存目錄(sd卡中的download文件夾)
3:getExternalStorageDirectory() 獲取到外部存儲的目錄 一般指SDcard(/storage/sdcard0)
4:getExternalStorageState() 獲取外部設置的當前狀態 一般指SDcard,比較常用的應該是 MEDIA_MOUNTED(SDcard存在並且可以進行讀寫)還有其他的一些狀態,可以在文檔中進行查找。
5:getRootDirectory() 獲取到Android Root路徑
以下是具體操作:
1,判斷SD卡是否存在
/** * 判斷SDCard是否存在 [當沒有外掛SD卡時,內置ROM也被識別為存在sd卡] * * @return */ public static boolean isSdCardExist() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); }
2,獲取SD卡根目錄
/** * 獲取SD卡根目錄路徑 * * @return */ public static String getSdCardPath() { boolean exist = isSdCardExist(); String sdpath = ""; if (exist) { sdpath = Environment.getExternalStorageDirectory() .getAbsolutePath(); } else { sdpath = "不適用"; } return sdpath; }
3,獲取默認的文件存放路徑
/** * 獲取默認的文件路徑 * * @return */ public static String getDefaultFilePath() { String filepath = ""; File file = new File(Environment.getExternalStorageDirectory(), "abc.txt"); if (file.exists()) { filepath = file.getAbsolutePath(); } else { filepath = "不適用"; } return filepath; }
4-1,使用FileInputStream讀取文件
try { File file = new File(Environment.getExternalStorageDirectory(), "test.txt"); FileInputStream is = new FileInputStream(file); byte[] b = new byte[inputStream.available()]; is.read(b); String result = new String(b); System.out.println("讀取成功:"+result); } catch (Exception e) { e.printStackTrace(); }
4-2,使用BufferReader讀取文件
try { File file = new File(Environment.getExternalStorageDirectory(), DEFAULT_FILENAME); BufferedReader br = new BufferedReader(new FileReader(file)); String readline = ""; StringBuffer sb = new StringBuffer(); while ((readline = br.readLine()) != null) { System.out.println("readline:" + readline); sb.append(readline); } br.close(); System.out.println("讀取成功:" + sb.toString()); } catch (Exception e) { e.printStackTrace(); }
案例代碼:
// 文件寫操作函數 private void write(String content) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定義File類對象 if (!file.getParentFile().exists()) { // 父文件夾不存在 file.getParentFile().mkdirs(); // 創建文件夾 } PrintStream out = null; // 打印流對象用於輸出 try { out = new PrintStream(new FileOutputStream(file, true)); // 追加文件 out.println(content); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { out.close(); // 關閉打印流 } } } else { // SDCard不存在,使用Toast提示用戶 Toast.makeText(this, "保存失敗,SD卡不存在!", Toast.LENGTH_LONG).show(); } } // 文件讀操作函數 private String read() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定義File類對象 if (!file.getParentFile().exists()) { // 父文件夾不存在 file.getParentFile().mkdirs(); // 創建文件夾 } Scanner scan = null; // 掃描輸入 StringBuilder sb = new StringBuilder(); try { scan = new Scanner(new FileInputStream(file)); // 實例化Scanner while (scan.hasNext()) { // 循環讀取 sb.append(scan.next() + "\n"); // 設置文本 } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (scan != null) { scan.close(); // 關閉打印流 } } } else { // SDCard不存在,使用Toast提示用戶 Toast.makeText(this, "讀取失敗,SD卡不存在!", Toast.LENGTH_LONG).show(); } return null; }
資源文件夾,在main下與res同級,與res不同的是,該目錄下的資源文件在打包apk時,會按原格式一並被打包。
有三種使用方法:
webView.loadUrl("file:///android_asset/test.html");//假設已經創建了一個WebView實例
//這裡的open只能打開文件,不能打開文件夾
InputStream inputStream = getResource().getAssets().open("test.html");
讀取列表、讀取圖片、讀音樂,assets目錄下包含一個images目錄和一個mp3文件xuwei.mp3,images目錄中包含一張圖片dog.jpg:
String[] fileNames = getAssets().list("images/");//讀列表
InputStream inputStream = getAssets().open("images/dog.jpg");//讀圖片
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
imageView.setImageBitmap(bitmap);
AssetFileDescriptor assetFileDescriptor = getAssets().openFd("xuwei.mp3");//得到asset文件描述符
player.reset();//假設已創建一個MediaPlayer實例
player.setDataResource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());
player.prepare();
player.start();
資源文件夾,在res目錄下,系統會為res目錄下的所有資源生成相應的資源ID,raw中的文件也不例外,所以可以通過ID去訪問res/raw目錄中的任何文件,而assets目錄中的文件就需要借助AssetManager去訪問了。
assets目錄允許下面有多級子目錄,而res/raw下不允許存在目錄結構。
讀raw下的xuwei.mp3文件:
InputStream is = getResources().openRawResource(R.raw.xuwei);
res目錄下的文件都可用getResources()方法讀取。
利用Java的File類開發一個SD卡文件浏覽器,通過Environment.getExternalStorageDirectory()訪問系統的SD卡目錄,然後通過File的listFiles()方法獲取指定目錄下的全部文件和文件夾。
布局文件如下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.trampcr.sdfileexplorer.MainActivity">
<TextView
android:id="@+id/path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center_horizontal" />
<ListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/path" />
<Button
android:id="@+id/parent"
android:layout_width="38dp"
android:layout_height="34dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/home" />
</RelativeLayout>
布局文件包含一個TextView用於顯示當前路徑,ListView顯示當前目錄下文件和文件夾,Button用於返回上一級目錄。
ListView中的子布局,包含一個ImageView和一個TextView:
line.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="50dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@+id/icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/folder"/>
<TextView
android:id="@+id/file_name"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="abc"/>
</LinearLayout>
主程序代碼如下:
public class MainActivity extends AppCompatActivity {
private ListView mListView;
private TextView mTextView;
//記錄當前的父文件夾
private File mCurrentParent;
//記錄當前路徑下的所有文件的文件數組
File[] mCurrentFiles;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.list);
mTextView = (TextView) findViewById(R.id.path);
//獲取系統的SD卡的目錄
File root = new File(String.valueOf(Environment.getExternalStorageDirectory()));
//如果SD卡存在
if (root.exists()){
mCurrentParent = root;
mCurrentFiles = root.listFiles();
//使用當前目錄下的全部文件、文件夾來填充ListView
inflateListView(mCurrentFiles);
}
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mCurrentFiles[position].isFile()){
return;
}
File[] tmp = mCurrentFiles[position].listFiles();
if (tmp == null || tmp.length == 0){
Toast.makeText(MainActivity.this, "當前路徑不可訪問或該路徑下沒有文件", Toast.LENGTH_SHORT).show();
}else {
mCurrentParent = mCurrentFiles[position];
mCurrentFiles = tmp;
inflateListView(mCurrentFiles);
}
}
});
//獲取上一級目錄的按鈕
Button parent = (Button) findViewById(R.id.parent);
parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (!mCurrentParent.getCanonicalFile().equals("/mnt/shell/emulated/0")){
mCurrentParent = mCurrentParent.getParentFile();
mCurrentFiles = mCurrentParent.listFiles();
inflateListView(mCurrentFiles);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
private void inflateListView(File[] files) {
//創建一個List集合,List集合的元素是Map
List<Map<String, Object>> listItems = new ArrayList<>();
for (int i = 0; i < files.length; i++) {
Map<String, Object> listItem = new HashMap<>();
if (files[i].isDirectory()){
listItem.put("icon", R.drawable.folder);
}else {
listItem.put("icon", R.drawable.file);
}
listItem.put("fileName", files[i].getName());
listItems.add(listItem);
}
//創建一個SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.line, new String[]{"icon", "fileName"}, new int[]{R.id.icon, R.id.file_name});
mListView.setAdapter(simpleAdapter);
try {
mTextView.setText("當前路徑為:" + mCurrentParent.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用File[]數組填充ListView,填充是程序會根據File[]數組裡的數據元素代表的是文件還是文件夾來選擇使用文件圖標或文件夾圖標。
運行上面程序,可以看到:
Parse 移動 SDK 為 iOS、Android 和 Windows 應用程序提供了基於雲的 API 和服務。Parse SDK 還提供 了 JavaScript 和
在例子Android簡明開發教程十七:Dialog 顯示圖像 中我們留了一個例子DrawMap()沒有實現,這個例子顯示在線地圖,目前大部分地圖服務器都是將地圖以圖片存儲
想要理解ContentProvider的最佳方式就是自己動手去嘗試一下。下面介紹如何使用一個內置的Contacts ContentProvider。1. 創建一個工程,P
在我的設備上面,默認的首選項名字是net.manoel.UsingPreferences_preferences.xml,這個名字是使 用包名作為前綴的。然而,給首選項定