android內部存儲外部存儲以及assets文件的操作一些操作

由於項目需求,需要在應用本身的包中進行操作,其他程序是無法訪問。既然是應用本身包中,那應該就是內部存儲。

在模擬器上是無法體現內部存儲和外部存儲效果的。因爲外部存儲也可以實現。但是在真機上,外部存儲就不能操作。這個需要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









發佈了36 篇原創文章 · 獲贊 21 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章