package com.tws.plugin.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import tws.component.log.TwsLog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import android.widget.Toast;
import com.tws.plugin.core.PluginLoader;
public class FileUtil {
private static final boolean DEBUG = false;
private static final String TAG = "rick_Print:FileUtil";
public static final String ASSETS_PLUGINS = "assets/plugins/";
public static final String ICON_FOLDER = "plugins";
public static final String LIB_FOLDER = "lib";
public static final String DALVIK_CACHE_FOLDER = "dalvik-cache";
private static final String PREFIX_ICON_PATH = "assets" + File.separator + ICON_FOLDER + File.separator;
private static final String PREFIX_LIB_PATH = LIB_FOLDER + File.separator;
public static final String FIX_ICON_NAME = ".png"; // 注意这里是小写的
public static final String FIX_LIB_NAME = ".so";
public static final String XHDPI = "drawable-xhdpi";
public static final String XXHDPI = "drawable-xxhdpi";
public static final String XXXHDPI = "drawable-xxxhdpi";
private static float fdensity = 0.0f;// 1080p 是3.0f
public static final float XXHDPI_DENSITY = 3.0f;
public static boolean copyFile(String source, String dest) {
try {
return copyFile(new FileInputStream(new File(source)), dest);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
public static boolean copyFile(final InputStream inputStream, String dest) {
TwsLog.d(TAG, "copyFile to " + dest);
if (Build.VERSION.SDK_INT >= 23) {// Build.VERSION_CODES.M)
if (dest.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
// rick_Note Write code here^
int permissionState = PackageManager.PERMISSION_GRANTED;// PluginLoader.getApplication().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionState != PackageManager.PERMISSION_GRANTED) {
// 6.0的系统即使申请了读写sdcard的权限,仍然可以在设置中关闭, 则需要requestPermissons
TwsLog.e(TAG, "6.0以上的系统, targetSDK>=23时, sdcard读写默认为未授权,需requestPermissons或者在设置中开启:" + dest);
return false;
}
}
}
FileOutputStream oputStream = null;
try {
File destFile = new File(dest);
File parentDir = destFile.getParentFile();
if (!parentDir.isDirectory() || !parentDir.exists()) {
destFile.getParentFile().mkdirs();
}
oputStream = new FileOutputStream(destFile);
byte[] bb = new byte[48 * 1024];
int len = 0;
while ((len = inputStream.read(bb)) != -1) {
oputStream.write(bb, 0, len);
}
oputStream.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oputStream != null) {
try {
oputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
public static boolean copySo(File sourceDir, String so, String dest) {
TwsLog.d(TAG, "copySo - sourceDir=" + sourceDir + " so is " + so + " dest=" + dest);
try {
boolean isSuccess = false;
if (Build.VERSION.SDK_INT >= 21) {
String[] abis = Build.SUPPORTED_ABIS;
if (abis != null) {
for (String abi : abis) {
TwsLog.d(TAG, "try supported abi:" + abi);
String name = LIB_FOLDER + File.separator + abi + File.separator + so;
File sourceFile = new File(sourceDir, name);
if (sourceFile.exists()) {
isSuccess = copyFile(sourceFile.getAbsolutePath(), dest + File.separator + LIB_FOLDER
+ File.separator + so);
// api21 64位系统的目录可能有些不同
// copyFile(sourceFile.getAbsolutePath(), dest +
// File.separator + name);
break;
}
}
}
} else {
TwsLog.d(TAG, "supported api:" + Build.CPU_ABI + " " + Build.CPU_ABI2);
String name = LIB_FOLDER + File.separator + Build.CPU_ABI + File.separator + so;
File sourceFile = new File(sourceDir, name);
if (!sourceFile.exists() && Build.CPU_ABI2 != null) {
name = LIB_FOLDER + File.separator + Build.CPU_ABI2 + File.separator + so;
sourceFile = new File(sourceDir, name);
if (!sourceFile.exists()) {
name = LIB_FOLDER + File.separator + "armeabi" + File.separator + so;
sourceFile = new File(sourceDir, name);
}
}
if (sourceFile.exists()) {
isSuccess = copyFile(sourceFile.getAbsolutePath(), dest + File.separator + LIB_FOLDER
+ File.separator + so);
}
}
if (!isSuccess) {
TwsLog.e(TAG, "安装 :" + so + " 失败: NO_MATCHING_ABIS");
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
Toast.makeText(PluginLoader.getApplication(), "安装 " + so + " 失败: NO_MATCHING_ABIS",
Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
public static float getDensity() {
if (0.0f == fdensity) {
WindowManager wm = (WindowManager) PluginLoader.getApplication().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
fdensity = dm.density;
}
return fdensity;
}
public static boolean copyIcon(File sourceDir, String icon, String dest) {
getDensity();
String iconFolder = XXHDPI;
if (XXHDPI_DENSITY < fdensity) {
iconFolder = XXXHDPI;
} else if (fdensity < XXHDPI_DENSITY && 0.0f != fdensity) {
iconFolder = XHDPI;
}
try {
boolean isSuccess = false;
String name = PREFIX_ICON_PATH + File.separator + iconFolder + File.separator + icon;
File sourceFile = new File(sourceDir, name);
if (!sourceFile.exists()) {
if (XXHDPI_DENSITY < fdensity) {
name = PREFIX_ICON_PATH + File.separator + XXHDPI + File.separator + icon;
sourceFile = new File(sourceDir, name);
if (!sourceFile.exists()) {
name = PREFIX_ICON_PATH + File.separator + XHDPI + File.separator + icon;
sourceFile = new File(sourceDir, name);
}
} else if (XXHDPI_DENSITY == fdensity) {
name = PREFIX_ICON_PATH + File.separator + XXXHDPI + File.separator + icon;
sourceFile = new File(sourceDir, name);
if (!sourceFile.exists()) {
name = PREFIX_ICON_PATH + File.separator + XHDPI + File.separator + icon;
sourceFile = new File(sourceDir, name);
}
} else {
name = PREFIX_ICON_PATH + File.separator + XXHDPI + File.separator + icon;
sourceFile = new File(sourceDir, name);
if (!sourceFile.exists()) {
name = PREFIX_ICON_PATH + File.separator + XXXHDPI + File.separator + icon;
sourceFile = new File(sourceDir, name);
}
}
if (!sourceFile.exists()) {
name = PREFIX_ICON_PATH + File.separator + icon;
sourceFile = new File(sourceDir, name);
}
}
if (sourceFile.exists()) {
isSuccess = copyFile(sourceFile.getAbsolutePath(), dest + File.separator + ICON_FOLDER + File.separator
+ icon);
}
if (!isSuccess) {
TwsLog.e(TAG, "获取 :" + icon + " 失败: NO_MATCHING");
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
Toast.makeText(PluginLoader.getApplication(), "获取 " + icon + " 失败: NO_MATCHING", Toast.LENGTH_SHORT)
.show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* 解析必要的资源:so、图标等
*
* @return Set
*/
public static Set<String> unZipNecessaryRes(String apkFile, File tempDir) {
HashSet<String> result = null;
if (!tempDir.exists()) {
tempDir.mkdirs();
}
TwsLog.d(TAG, "开始解析获取必要的资源:" + tempDir.getAbsolutePath());
ZipFile zfile = null;
boolean isSuccess = false;
BufferedOutputStream fos = null;
BufferedInputStream bis = null;
try {
zfile = new ZipFile(apkFile);
ZipEntry ze = null;
Enumeration zList = zfile.entries();
while (zList.hasMoreElements()) {
ze = (ZipEntry) zList.nextElement();
String relativePath = ze.getName();
if (!relativePath.startsWith(PREFIX_LIB_PATH) && !relativePath.startsWith(PREFIX_ICON_PATH)) {
if (DEBUG) {
TwsLog.d(TAG, "不是lib也不是插件资源目录,跳过:" + relativePath);
}
continue;
}
if (ze.isDirectory()) {
File folder = new File(tempDir, relativePath);
if (DEBUG) {
TwsLog.d(TAG, "正在创建目录:" + folder.getAbsolutePath());
}
if (!folder.exists()) {
folder.mkdirs();
}
} else {
if (result == null) {
result = new HashSet<String>(4);
}
File targetFile = new File(tempDir, relativePath);
TwsLog.d(TAG, "正在解压必要的资源文件:" + targetFile.getAbsolutePath());
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
targetFile.createNewFile();
fos = new BufferedOutputStream(new FileOutputStream(targetFile));
bis = new BufferedInputStream(zfile.getInputStream(ze));
byte[] buffer = new byte[2048];
int count = -1;
while ((count = bis.read(buffer)) != -1) {
fos.write(buffer, 0, count);
fos.flush();
}
fos.close();
fos = null;
bis.close();
bis = null;
result.add(relativePath.substring(relativePath.lastIndexOf(File.separator) + 1));
}
}
isSuccess = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (zfile != null) {
try {
zfile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TwsLog.d(TAG, "解压必要的资源文件结束 " + isSuccess);
return result;
}
public static void readFileFromJar(String jarFilePath, String metaInfo) {
TwsLog.d(TAG, "call readFileFromJar(" + jarFilePath + ", " + metaInfo + ")");
JarFile jarFile = null;
try {
jarFile = new JarFile(jarFilePath);
JarEntry entry = jarFile.getJarEntry(metaInfo);
if (entry != null) {
InputStream input = jarFile.getInputStream(entry);
return;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (jarFile != null) {
try {
jarFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return;
}
/**
* 递归删除文件及文件夹
*
* @param file
*/
public static boolean deleteAll(File file) {
if (file.isDirectory()) {
File[] childFiles = file.listFiles();
if (childFiles != null && childFiles.length > 0) {
for (int i = 0; i < childFiles.length; i++) {
deleteAll(childFiles[i]);
}
}
}
TwsLog.d(TAG, "delete:" + file.getAbsolutePath());
return file.delete();
}
public static void printAll(File file) {
if (file.isDirectory()) {
File[] childFiles = file.listFiles();
if (childFiles != null && childFiles.length > 0) {
for (int i = 0; i < childFiles.length; i++) {
printAll(childFiles[i]);
}
}
}
}
public static String streamToString(InputStream input) throws IOException {
InputStreamReader isr = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr);
String line;
StringBuffer sb = new StringBuffer();
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
isr.close();
return sb.toString();
}
}