由于项目需求,需要在应用本身的包中进行操作,其他程序是无法访问。既然是应用本身包中,那应该就是内部存储。
在模拟器上是无法体现内部存储和外部存储效果的。因为外部存储也可以实现。但是在真机上,外部存储就不能操作。这个需要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