Android開發實作內部和外部存盤檔案
效果圖:

activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="檔案名字:"
android:textSize="35dp"></TextView>
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="35dp"></EditText>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="檔案內容:"
android:textSize="35dp"></TextView>
<EditText
android:id="@+id/et_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="35dp"></EditText>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_weight="1"
android:text="存入INTERNAL檔案"
android:onClick="Save_in"></Button>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_weight="1"
android:text="存入EXTERNAL檔案"
android:onClick="Save_ex"></Button>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Internal檔案內容:"
android:textSize="30dp">
</TextView>
<TextView
android:id="@+id/incontent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="External檔案內容:"
android:textSize="30dp">
</TextView>
<TextView
android:id="@+id/excontent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp">
<Button
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="從INTERNAL取檔案"
android:onClick="Out_in"></Button>
<Button
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="從EXTERNAL取檔案"
android:onClick="Out_ex"></Button>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java代碼:
package com.henu.saveinfile;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.file.FileVisitOption;
public class MainActivity extends AppCompatActivity {
private EditText et_name;
private EditText et_content;
private TextView tv_in_content;
private TextView tv_ex_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = (EditText) findViewById(R.id.et_name);
et_content = (EditText) findViewById(R.id.et_content);
tv_in_content = (TextView) findViewById(R.id.incontent);
tv_ex_content = (TextView) findViewById(R.id.excontent);
//彈出請求獲取存盤權限的對話框
int REQUEST_EXTERNAL_STORAGE = 1;
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
int permission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
MainActivity.this,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
//存入內部存盤區
public void Save_in(View v) {
FileOutputStream fos;
try {
fos = openFileOutput(et_name.getText().toString().trim(), Context.MODE_PRIVATE);
fos.write(et_content.getText().toString().trim().getBytes());
fos.close();
Toast.makeText(this, "存入內部成功", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//從內部存盤區取出檔案并顯示
public void Out_in(View v) {
FileInputStream fis;
try {
fis = openFileInput(et_name.getText().toString().trim());
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
tv_in_content.setText(getFilesDir() + "/" + et_name.getText().toString().trim() + ".txt" + ":" + new String(buffer));
fis.close();
Toast.makeText(this, "從內部讀取成功", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//判斷外部存盤區是否可用
public boolean isExternalStorageWritable() {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
return true;
}
return false;
}
//把檔案存入外部存盤區
public void Save_ex(View v) {
if (isExternalStorageWritable()) {
File file = new File(Environment.getExternalStorageDirectory(), et_name.getText().toString().trim() + ".txt");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(et_content.getText().toString().trim().getBytes());
Toast.makeText(this, "創建成功", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
Toast.makeText(this, "請允許\"SavelInFile\"訪問您設備上的照片、\n" +
"媒體內容和檔案\n", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(this, "外部存盤區不可用", Toast.LENGTH_SHORT).show();
}
}
//取出外部檔案并顯示出來
public void Out_ex(View v) {
File file = new File(Environment.getExternalStorageDirectory(), et_name.getText().toString().trim() + ".txt");
FileInputStream fis;
try {
fis = new FileInputStream(file);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
tv_ex_content.setText(Environment.getExternalStorageDirectory().getPath() + "/" + et_name.getText().toString().trim() + ".txt" + ":" + new String(buffer));
Toast.makeText(this, "從外部讀取成功", Toast.LENGTH_SHORT).show();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
AndroidManifest.xml代碼:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.henu.saveinfile">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>//獲取外部存盤區寫的權限(有了寫的權限就能有了讀的權限)
<application
android:requestLegacyExternalStorage="true"//停用磁區存盤
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SaveInFile">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
遇到的問題:
在外部存盤檔案時老是報錯:FileNotFoundException,找不到檔案,一般這樣的問題有兩個原因,一個是路徑錯誤,一個是沒有權限,我這是在創建檔案時報錯,所以原因是后者,但是我已經在AndroidManifest.xml檔案中加入android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>獲取到權限了,為什么還是報錯,原來是安卓6版本以上,需要獲取運行時權限,我又在加上對話框,在初次進入時彈出詢問用戶獲取權限,
但是還是報錯,FileNotFoundException,查了下原因,原來是Android 10之前,Android的檔案存盤現象就像個垃圾桶,但凡app取得了存盤空間的讀寫權限WRITE_EXTERNAL_STORAGE,就可以肆意創建檔案,難以管理,用戶體驗也特別差,打開檔案管理器,會發現,想找個具體的檔案根本無從下手,為了更好地管理自己的檔案并減少混亂,加強隱私保護,Android Q開始引入了磁區存盤機制,外部存盤空間被重新設計,按應用私有和公用共享劃分,應用只能訪問到自己私有空間,或者通過MediaStore API 和Storage Access Framework去訪問共享的資源目錄,
關閉了磁區存盤:android:requestLegacyExternalStorage="true"就能和原來一樣在外部存盤區肆意創建檔案了 哈哈

參考https://zhuanlan.zhihu.com/p/351713186
參考https://blog.csdn.net/qxs965266509/article/details/50606385?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161760026116780265414814%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161760026116780265414814&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-50606385.pc_search_result_no_baidu_js&utm_term=Android+filenotfoundexception
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/273263.html
標籤:其他
上一篇:Enrace的博客
