public static void copyAssets(Context context, String oldPath, String newPath) {
try {
String fileNames[] = context.getAssets().list(oldPath);// 获取assets目录下的所有文件及目录名
if (fileNames.length > 0) {// 如果是目录
File file = new File(newPath);
file.mkdirs();// 如果文件夹不存在,则递归
for (String fileName : fileNames) {
copyAssets(context, oldPath + "/" + fileName, newPath + "/" + fileName);
}
} else {// 如果是文件
InputStream is = context.getAssets().open(oldPath);
FileOutputStream fos = new FileOutputStream(new File(newPath));
byte[] buffer = new byte[1024];
int byteCount = 0;
while ((byteCount = is.read(buffer)) != -1) {// 循环从输入流读取
// buffer字节
fos.write(buffer, 0, byteCount);// 将读取的输入流写入到输出流
}
fos.flush();// 刷新缓冲区
is.close();
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
调用方式
copyAssets(MainActivity.this,"python3.7.zip","/data/data/"+packageName+"/"+"python3.7.zip");
这里,python3.7.zip
为assets文件夹下的文件。
目标文件夹也可以是context.getFilesDir()
后的内部存储路径。即"/data/data/"+packageName+"/files/"+"filename"
建议异步处理
AsyncTask.execute(new Runnable() {
@Override
public void run() {
copyAssets(MainActivity.this,"python3.7.zip","/data/data/"+packageName+"/"+"python3.7.zip");
Toast.makeText(MainActivity.this, "Finish", Toast.LENGTH_SHORT).show();
}
});
ps:
private void copyFile(Activity c, String Name,String desPath) throws IOException {
File outfile = null;
if( desPath != null )
outfile = new File("/data/data/"+getPackageName()+"/files/"+desPath+Name);
else
outfile = new File("/data/data/"+getPackageName()+"/files/"+Name);
if (!outfile.exists()) {
outfile.createNewFile();
FileOutputStream out = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
InputStream in;
int readLen = 0;
if( desPath != null )
in = c.getAssets().open(desPath+Name);
else
in = c.getAssets().open(Name);
while((readLen = in.read(buffer)) != -1){
out.write(buffer, 0, readLen);
}
out.flush();
in.close();
out.close();
}
}
方式二
亦或使用
源码
package com.example.androidpython;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.preference.PreferenceManager;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class AssetExtractor {
private final static String LOGTAG = "AssetExtractor";
private Context mContext;
private AssetManager mAssetManager;
public AssetExtractor(Context context) {
mContext = context;
mAssetManager = context.getAssets();
}
/**
* Sets a version for the extracted assets version.
*
* @param version: int
*/
public void setAssetsVersion(int version) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("assetsVersion", version);
editor.apply();
}
/**
* Returns the version for the extracted assets.
*
* @return int
*/
public int getAssetsVersion() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
return preferences.getInt("assetsVersion", 0);
}
/**
* Returns a list of assets in the APK.
*
* @param path: the path in the assets folder.
* @return the list of assets.
*/
public List<String> listAssets(String path) {
List<String> assets = new ArrayList<>();
try {
String assetList[] = mAssetManager.list(path);
if (assetList.length > 0) {
for (String asset : assetList) {
List<String> subAssets = listAssets(path + '/' + asset);
assets.addAll(subAssets);
}
} else {
assets.add(path);
}
} catch (IOException e) {
e.printStackTrace();
}
return assets;
}
/**
* Returns the path to the assets data dir on the device.
*
* @return String with the data dir path.
*/
public String getAssetsDataDir() {
String appDataDir = mContext.getApplicationInfo().dataDir;
return appDataDir + "/assets/";
}
/**
* Copies an asset from the APK to the device.
*
* @param src: the source path in the APK.
* @param dst: the destination path in the device.
*/
private void copyAssetFile(String src, String dst) {
File file = new File(dst);
Log.i(LOGTAG, String.format("Copying %s -> %s", src, dst));
try {
File dir = file.getParentFile();
if (!dir.exists()) {
dir.mkdirs();
}
InputStream in = mAssetManager.open(src);
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int read = in.read(buffer);
while (read != -1) {
out.write(buffer, 0, read);
read = in.read(buffer);
}
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Copies the assets from the APK to the device.
*
* @param path: the source path
*/
public void copyAssets(String path) {
for (String asset : listAssets(path)) {
copyAssetFile(asset, getAssetsDataDir() + asset);
}
}
/**
* Recursively deletes the contents of a folder.
*
* @param file: the File object.
*/
private void recursiveDelete(File file) {
if (file.isDirectory()) {
for (File f : file.listFiles())
recursiveDelete(f);
}
Log.i(LOGTAG, "Removing " + file.getAbsolutePath());
file.delete();
}
/**
* Removes recursively the assets from the device.
*
* @param path: the path to the assets folder
*/
public void removeAssets(String path) {
File file = new File(getAssetsDataDir() + path);
recursiveDelete(file);
}
/**
* Returns if the path exists in the device assets.
*
* @param path: the path to the assets folder
* @return Boolean
*/
public Boolean existsAssets(String path) {
File file = new File(getAssetsDataDir() + path);
return file.exists();
}
}
用法:
(在工程的assets目录创建python文件夹,将所有包复制进该目录,在app启动的适当时候,调用以下代码拷贝assets中(python文件夹内的)的所有文件到手机存储)
// Extract python files from assets
AssetExtractor assetExtractor = new AssetExtractor(MainActivity.this);
assetExtractor.removeAssets("python");
assetExtractor.copyAssets("python");
// Get the extracted assets directory
String pyPath = assetExtractor.getAssetsDataDir() + "python";
网友评论