由於項目需求,需要在應用本身的包中進行操作,其他程序是無法訪問。既然是應用本身包中,那應該就是內部存儲。
在模擬器上是無法體現內部存儲和外部存儲效果的。因爲外部存儲也可以實現。但是在真機上,外部存儲就不能操作。這個需要root權限。沒有root權限,是無法操作的。
內部存儲是不需要root權限的,直接有路徑就可以操作,因爲爲了實現功能,我測試了很多方法,最後才成功。
接下來就是代碼,具體內容在代碼註釋中體現。
如果讀寫存儲時,直接給定路徑,例如直接寫成死的:data/data/com.package.name/aaa...的話,這樣就是外部存儲,沒有root權限好像是不能訪問的。
如果想要寫在自己應用本身的內部下,那就是內部存儲,這樣調用是不需要root。
這時候就有一個方法,getFIleDir() 獲得的路徑是data/data/包名/files路徑。如果想要自定義路徑,在下面的具體代碼中有實現。請參考。
getFileDir()這個方法本身獲得的就是內部存儲,看一下開發文檔的內容翻譯如下:
/**
* 讀取assets文件夾下的某個文件
* 你可以自己建一個txt文件,然後進行操作
*/
public void readAssets() {
try {
// assets文件夾下的文件
InputStream is = getAssets().open(
"applist/applist.preincluded.description");
// 獲得文件的內容大小
int size = is.available();
// 把這個大小給了存儲數組的大小
byte[] buffer = new byte[size];
is.read(buffer);
// 關閉流
is.close();
// 讀取出來的正常內容(包括空格)
String text = new String(buffer, "UTF-8");
// 將讀取出來的內容中的所有空格都替換掉
String textResult = text.replace(" ", "");
System.out.println(textResult);
// 如果不換行輸出,就顯示不出來,不知道爲什麼
// System.out.print(text);
} catch (IOException e) {
// Should never happen!
throw new RuntimeException(e);
}
}
<span style="white-space:pre"> </span>try {
ctxDealFile = this.createPackageContext("com.example.test",
Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String uiFileName = "applist";
deepFile(ctxDealFile, uiFileName);
/** 上邊的內容卸載onCreate中
* 遍歷assets下的所有文件
* @param ctxDealFile
* @param path
*/
public void deepFile(Context ctxDealFile, String path) {
try {
String str[] = ctxDealFile.getAssets().list(path);
if (str.length > 0) {// 如果是目錄
File file = new File("/data/" + path);
file.mkdirs();
for (String string : str) {
path = path + "/" + string;
System.out.println("zhoulc:\t" + path);
// textView.setText(textView.getText()+"\t"+path+"\t");
deepFile(ctxDealFile, path);
path = path.substring(0, path.lastIndexOf('/'));
}
} else {// 如果是文件
InputStream is = ctxDealFile.getAssets().open(path);
FileOutputStream fos = new FileOutputStream(new File("/data/"
+ path));
byte[] buffer = new byte[1024];
int count = 0;
while (true) {
count++;
int len = is.read(buffer);
if (len == -1) {
break;
}
fos.write(buffer, 0, len);
}
is.close();
fos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
<span style="white-space:pre"> </span>/**
*
* 將assets的文件寫到固定目錄下
*/
private void importDB() {
File file = new File("data/data/com.example.test/",
"applist/applist.preincluded.description");
// String DbName = "people_db";
// 判斷是否存在
if (file.exists() && file.length() > 0) {
} else {
// 使用AssetManager類來訪問assets文件夾
AssetManager asset = getAssets();
InputStream is = null;
FileOutputStream fos = null;
try {
is = asset.open("applist/applist.preincluded.description");
fos = new FileOutputStream(file);
int len = 0;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
<span style="white-space:pre"> </span>/**
* 將assets文件夾的內容複製到固定目錄下
*
* @param myContext
* @param ASSETS_NAME要複製的文件名
* @param savePath 要保存的路徑
* @param saveName 複製後的文件名
*
* 參考:http://www.dewen.io/q/5544/
* http://www.tuicool.com/articles/JNbqEj
*/
public static void copy(Context myContext, String ASSETS_NAME,
String savePath, String saveName) {
String filename = savePath + saveName;
File dir = new File(savePath);
// 如果目錄不中存在,創建這個目錄
if (!dir.exists())
dir.mkdirs();
try {
if (!(new File(filename)).exists()) {
InputStream is = myContext.getResources().getAssets()
.open(ASSETS_NAME);
FileOutputStream fos = new FileOutputStream(filename);
byte[] buffer = new byte[7168];
int count = 0;
while ((count = is.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
fos.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
<span style="white-space:pre"> </span>imageView = (ImageView) findViewById(R.id.image);
/**
* 使用assets下的圖片
* http://www.2cto.com/kf/201408/322920.html
*/
InputStream is;
try {
is = this.getAssets().open("applist/applogo.png");
Bitmap bmp = BitmapFactory.decodeStream(is);
imageView.setImageBitmap(bmp);
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
<span style="white-space:pre"> </span>/**
* 往固定的目錄下的文件中寫內容
* @param fileName 要操作的絕對路徑/data/data/包名/路徑+文件名
* @param write_str 要寫入的內容
* @throws IOException
*/
public void writeSDFile(String fileName, String write_str)
throws IOException {
File file = new File(fileName);
FileOutputStream fos = new FileOutputStream(file);
FileOutputStream fos1 = openFileOutput(fileName,
MainActivity.this.MODE_PRIVATE);
byte[] bytes = write_str.getBytes();
fos1.write(bytes);
fos.close();
}
/**
* 讀取固定目錄下的文件(外部存儲的操作。真機沒有root是不可以的)
* @param fileName
* @return
* @throws IOException
* 參考博客:http://blog.csdn.net/ztp800201/article/details/7322110
*/
public String readSDFile(String fileName) throws IOException {
File file = new File(fileName);
// fileinputstream是不能傳入路徑的,只傳入名稱就找不到文件。所以需要傳入file
FileInputStream fis = new FileInputStream(file);
FileInputStream fis1 = openFileInput(fileName);
int length = fis1.available();
byte[] buffer = new byte[length];
fis1.read(buffer);
String res = EncodingUtils.getString(buffer, "UTF-8");
fis1.close();
return res;
}
<span style="white-space:pre"> </span>/**
* 內部存儲的寫方法
*/
public void writeNeibu() {
String str = "測試內容111";
// getFileDir()方法獲得是file的路徑,就是data/data/包名/file
// 但是我想在自定義的路徑下生成文件,我就獲得file路徑的父路徑
File dataDir = getFilesDir().getParentFile();
File mydir = new File(dataDir, "aaa");
// 創建data/data/包名/aaa路徑
mydir.mkdir();
File file = new File(mydir, "test.txt");
BufferedWriter bw = null;
try {
file.createNewFile();
// fileoutputstream的第二個參數,就是決定是否追加 ,false爲替換,true就會在尾部追加內容
bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file, false), "UTF-8"));
// fw.append("測試內容");
bw.write(str);
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 內部存儲的讀方法
*/
public void readNeibu() {
File dataDir = getFilesDir().getParentFile();
File mydir = new File(dataDir, "aaa");
File file = new File(mydir, "test.txt");
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(
file), "UTF-8"));
String str1 = null;
int a;
while ((a = br.read()) != -1) {
str1 = br.readLine();
System.out.println(str1);
}
br.close();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
由於將apk下載到內部存儲,安裝時直接給路徑,是無法調用的。因爲外部不能調用應用內部文件,沒有權限。
此時進行安裝,就應該先將內部文件轉移到外部,在從外部調用安裝。
這裏先用mkdir創建目錄,在用createNewFile創建文件。
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
InputStream is = getAssets().open("abc.apk");
File file = new File(Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/aaa");
if (!file.exists()) {
file.mkdir();
}
File file2 = new File(file, "abc.apk");
if (!file2.exists()) {
file2.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file2);
byte[] temp = new byte[1024];
int i = 0;
while ((i = is.read(temp)) > 0) {
fos.write(temp, 0, i);
}
fos.close();
is.close();
Intent intent1 = new Intent(Intent.ACTION_VIEW);
// Intent intent = new
// Intent(Intent.ACTION_INSTALL_PACKAGE);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.setDataAndType(Uri.parse("file://"
+ Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/aaa/abc.apk"),
"application/vnd.android.package-archive");
startActivity(intent1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/aaa/abc.apk");
System.out.println("--->" + file.exists());
}
});
參考博客:
Android中關於內部存儲的一些重要函數 :http://blog.csdn.net/hudashi/article/details/8037076
Android 開發之網絡文件下載 :http://blog.sina.com.cn/s/blog_4c451e0e0101a8zd.html
appliacation私有文件訪問--/data/data/packagename/ : http://aijiawang-126-com.iteye.com/blog/792931
Android中如何實現文件下載 : http://blog.sina.com.cn/s/blog_5f35912f0100zut7.html
Android程序中實現APK的安裝 : http://blog.csdn.net/sunchaoenter/article/details/6683032
關於android
如何安裝 assets文件下的apk : http://blog.csdn.net/shen332401890/article/details/8826827