代码块
package com.example.panshuang.test;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**
* Created by pan.shuang on 2020/8/11.
*/
public class NaviOfflineDataActivity extends Activity {
private static final String TAG = "NaviOfflineDataActivity";
private static final String FROM_FOLDER_PATH = "/storage/usbotg/AutoNaviData/chn";
private static final String TO_FOLDER_PATH = "/navi/AutoNaviData/chn";
private static final String FROM_MD5_FOLDER_PATH = "/storage/usbotg/AutoNaviData/md5";
private static final String FROM_COPY_MD5_FOLDER_PATH = "/navi/AutoNaviData/md5";
private static final String TO_MD5_FOLDER_PATH = "/navi/md5";
private static final String MD5_FILE_NAME = "chnmd5.txt";
private static final String FROM_MD5_FILE_PATH = FROM_MD5_FOLDER_PATH + "/" + MD5_FILE_NAME;
private static final String FROM_COPY_MD5_FILE_PATH = FROM_COPY_MD5_FOLDER_PATH + "/" + MD5_FILE_NAME;
private static final String TO_MD5_FILE_PATH = TO_MD5_FOLDER_PATH + "/" + MD5_FILE_NAME;
private static final int MUIL_CLICK_DURATION = 500;
long mLastClickTime;
int mClickCount;
boolean mIsVisiable;
Button mCopyButton;
Button mDeleteButton;
Button mMD5Button;
Button mCreateMD5Button;
Button mCopyMD5Button;
Button mForceStopButton;
TextView mTextView;
AlertDialog mAlertDialog;
Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navi_offline_data_layout);
mHandler = new Handler();
//显示操作状态,连续点击10次可显示或隐藏MD5生成、导入和强行停止选项
mTextView = findViewById(R.id.copy_text);
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
long newClickTime = SystemClock.uptimeMillis();
long duration = newClickTime - mLastClickTime;
if (duration > 0 && duration < MUIL_CLICK_DURATION){
mClickCount ++;
if (mClickCount == 10){
mCreateMD5Button.setVisibility(mIsVisiable ? View.VISIBLE : View.GONE);
mCopyMD5Button.setVisibility(mIsVisiable ? View.VISIBLE : View.GONE);
mForceStopButton.setVisibility(mIsVisiable ? View.VISIBLE : View.GONE);
mClickCount = 0;
mIsVisiable = !mIsVisiable;
}
}else {
mClickCount = 0;
}
mLastClickTime = SystemClock.uptimeMillis();
}
});
//从U盘导入离线数据和MD5文件
mCopyButton = findViewById(R.id.copy_button);
mCopyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTextView.setText("拷贝中,请不要拔掉U盘");
updateButtonClickable(false);
new Thread(new Runnable() {
@Override
public void run() {
//先删除之前拷贝的
FileUtils.deleteFolderOrFile(TO_FOLDER_PATH);
FileUtils.deleteFolderOrFile(FROM_COPY_MD5_FILE_PATH);
FileUtils.deleteFolderOrFile(TO_MD5_FILE_PATH);
//然后先拷贝MD5文件,再拷贝正式文件
FileUtils.copyFile(FROM_MD5_FILE_PATH,FROM_COPY_MD5_FOLDER_PATH,MD5_FILE_NAME);
final int result = FileUtils.copyFolder(FROM_FOLDER_PATH, TO_FOLDER_PATH);
mHandler.post(new Runnable() {
@Override
public void run() {
updateTextView("拷贝",result);
updateButtonClickable(true);
}
});
}
}).start();
}
});
//删除离线数据和MD5文件
mDeleteButton = findViewById(R.id.delete_button);
mDeleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTextView.setText("删除中");
updateButtonClickable(false);
new Thread(new Runnable() {
@Override
public void run() {
FileUtils.deleteFolderOrFile(TO_MD5_FOLDER_PATH);
final int result = FileUtils.deleteFolderOrFile(TO_FOLDER_PATH);
mHandler.post(new Runnable() {
@Override
public void run() {
updateTextView("删除",result);
updateButtonClickable(true);
}
});
}
}).start();
}
});
//对离线数据进行MD5校验,即对离线数据生成MD5文件,并与导入的MD5文件进行比对(如果没有导入则实时对U盘离线数据生成MD5文件)
mMD5Button = findViewById(R.id.md5_button);
mMD5Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTextView.setText("MD5校验中");
updateButtonClickable(false);
new Thread(new Runnable() {
@Override
public void run() {
final int result = FileUtils.compareMD5(FROM_FOLDER_PATH, TO_FOLDER_PATH, FROM_COPY_MD5_FOLDER_PATH, TO_MD5_FOLDER_PATH, MD5_FILE_NAME);
mHandler.post(new Runnable() {
@Override
public void run() {
updateTextView("MD5校验",result);
updateButtonClickable(true);
}
});
}
}).start();
}
});
//对U盘离线数据生成MD5文件至U盘
mCreateMD5Button = findViewById(R.id.md5_create_button);
mCreateMD5Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTextView.setText("MD5生成中,请不要拔掉U盘");
updateButtonClickable(false);
new Thread(new Runnable() {
@Override
public void run() {
final int result = FileUtils.createMD5File(FROM_FOLDER_PATH, FROM_MD5_FOLDER_PATH,MD5_FILE_NAME);
mHandler.post(new Runnable() {
@Override
public void run() {
updateTextView("MD5生成",result);
updateButtonClickable(true);
}
});
}
}).start();
}
});
//从U盘导入MD5文件
mCopyMD5Button = findViewById(R.id.md5_copy_button);
mCopyMD5Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTextView.setText("MD5拷贝中,请不要拔掉U盘");
updateButtonClickable(false);
new Thread(new Runnable() {
@Override
public void run() {
final int result = FileUtils.copyFile(FROM_MD5_FILE_PATH, FROM_COPY_MD5_FOLDER_PATH,MD5_FILE_NAME);
mHandler.post(new Runnable() {
@Override
public void run() {
updateTextView("MD5拷贝",result);
updateButtonClickable(true);
}
});
}
}).start();
}
});
//强行停止退出
mForceStopButton = findViewById(R.id.stop_button);
mForceStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(NaviOfflineDataActivity.this);
builder.setMessage("强行停止退出可能会导致未知异常,确定要这样做吗?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
System.exit(0);
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mAlertDialog.dismiss();
}
});
mAlertDialog = builder.create();
mAlertDialog.show();
}
});
}
public void updateButtonClickable(boolean clickable){
mCopyButton.setClickable(clickable);
mDeleteButton.setClickable(clickable);
mMD5Button.setClickable(clickable);
mCreateMD5Button.setClickable(clickable);
mCopyMD5Button.setClickable(clickable);
}
public void updateTextView(String start, int result){
String text;
switch (result){
case FileUtils.CMD_RESULT_SUCCESS:
text = start + "成功";
break;
case FileUtils.CMD_RESULT_FROM_FILE_NONEXIST:
text = start + "失败,错误码:" + result +" 源文件不存在";
break;
case FileUtils.CMD_RESULT_TO_FILE_NONEXIST:
text = start + "失败,错误码:" + result +" 目标文件不存在";
break;
case FileUtils.CMD_RESULT_FILE_NONSAME:
text = start + "失败,错误码:" + result +" 文件不一致";
break;
case FileUtils.CMD_RESULT_ONWER_DIED:
text = start + "失败,错误码:" + result +" 请确认U盘连接状态";
break;
default:
text = start + "失败,错误码:" + result;
break;
}
mTextView.setText(text);
}
}
- 工具类
代码块
package com.example.panshuang.test;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
/**
* Created by pan.shuang on 2020/8/12.
*/
public class FileUtils {
public static final String TAG = "FileUtils";
public static final int CMD_RESULT_UNKNOWN = -1;
public static final int CMD_RESULT_FROM_FILE_NONEXIST = -2;
public static final int CMD_RESULT_TO_FILE_NONEXIST = -3;
public static final int CMD_RESULT_FILE_NONSAME = -4;
public static final int CMD_RESULT_SUCCESS = 0;
public static final int CMD_RESULT_PERMISSION_DENIED = 13;
public static final int CMD_RESULT_ONWER_DIED = 130;
public static int copyFile(String fromFilePath, String toFolderPath, String toFileName) {
String toFilePath = toFolderPath + "/" + toFileName;
Log.d(TAG, "copyFile from " + fromFilePath + " to "+toFilePath);
int result;
try {
File fromFile = new File(fromFilePath);
if (!fromFile.exists() || fromFile.length() == 0 || fromFile.isDirectory() || !fromFile.isFile() || !fromFile.canRead()){
Log.e(TAG, "copyFile: " + fromFilePath + " usb file not exist.");
result = CMD_RESULT_FROM_FILE_NONEXIST;
return result;
}
Runtime runtime = Runtime.getRuntime();
if (!(new File(toFolderPath).exists())) {
java.lang.Process process = runtime.exec("mkdir -p " + toFolderPath);
process.waitFor();
}
java.lang.Process process = runtime.exec("cp " + fromFilePath + " " + toFilePath);
result = process.waitFor();
Log.d(TAG, "result=" + result);
if (result == 0) {
Log.d(TAG, "copyFile completed from fromFilePath to " + toFolderPath);
} else {
Log.d(TAG, "copyFile fail " + toFolderPath);
}
} catch (Exception e) {
Log.e(TAG, "copyFile "+ e.toString());
result = CMD_RESULT_UNKNOWN;
}
return result;
}
public static int copyFolder(String fromFolderPath, String toFolderPath) {
Log.d(TAG, "copyFolder from " + fromFolderPath + " to " + toFolderPath);
int result;
try {
File fromFile = new File(fromFolderPath);
if (!fromFile.exists() || fromFile.length() == 0 || !fromFile.canRead()) {
Log.e(TAG, "copyFolder: " + fromFolderPath + " usb file not exist.");
result = CMD_RESULT_FROM_FILE_NONEXIST;
return result;
}
Runtime runtime = Runtime.getRuntime();
if (!(new File(toFolderPath).exists())) {
java.lang.Process process = runtime.exec("mkdir -p " + toFolderPath);
process.waitFor();
}
java.lang.Process process = runtime.exec("cp -r " + fromFolderPath + "/. " + toFolderPath);
result = process.waitFor();
Log.d(TAG, "result=" + result);
if (result == 0) {
Log.d(TAG, "copyFolder completed from fromFilePath to " + toFolderPath);
} else {
Log.d(TAG, "copyFolder fail " + toFolderPath);
}
} catch (Exception e) {
Log.e(TAG, "copyFolder " + e.toString());
result = CMD_RESULT_UNKNOWN;
}
return result;
}
public static int deleteFolderOrFile(String deletePath) {
Log.d(TAG, "deleteFolderOrFile " + deletePath);
int result;
try {
File deleteFile = new File(deletePath);
if (!deleteFile.exists() || deleteFile.length() == 0 || !deleteFile.canRead()) {
result = CMD_RESULT_TO_FILE_NONEXIST;
return result;
}
Runtime runtime = Runtime.getRuntime();
java.lang.Process process = runtime.exec("rm -rf " + deletePath);
result = process.waitFor();
Log.d(TAG, "result=" + result);
if (result == 0) {
Log.d(TAG, "deleteFolderOrFile completed");
} else {
Log.d(TAG, "deleteFolderOrFile fail " + deletePath);
}
} catch (Exception e) {
Log.e(TAG, "deleteFolderOrFile " + e.toString());
result = CMD_RESULT_UNKNOWN;
}
return result;
}
public static int compareMD5(String fromFolderPath, String toFolderPath, String fromMD5FolderPath, String toMD5FolderPath, String MD5FileName) {
Log.d(TAG, "compareMD5 from " + fromFolderPath + " to " + toFolderPath);
String fromMD5FilePath = fromMD5FolderPath + "/" + MD5FileName;
String toMD5FilePath = toMD5FolderPath + "/" + MD5FileName;
int result;
java.lang.Process process;
try {
Runtime runtime = Runtime.getRuntime();
//先判断目标文件是否存在
File toFile = new File(toFolderPath);
if (!toFile.exists() || toFile.length() == 0 || !toFile.canRead()) {
result = CMD_RESULT_TO_FILE_NONEXIST;
return result;
}
//生成目标文件MD5文件夹
if (!(new File(toMD5FolderPath).exists())) {
process = runtime.exec("mkdir -p " + toMD5FolderPath);
process.waitFor();
}
//生成目标文件MD5文件
process = runtime.exec(new String[]{"sh","-c","find " + toFolderPath +
" -type f -print0 | xargs -0 md5sum | sort > " + toMD5FilePath});
result = process.waitFor();
Log.d(TAG, "tomd5 result=" + result);
//如果成功生成目标文件MD5文件则与源文件比对
if (result == 0 && new File(toMD5FilePath).length() > 0) {
Log.d(TAG, "tomd5 completed " + toFolderPath);
//判断源文件MD5文件是否存在,不存在则实时从源文件生成
File fromMD5File = new File(fromMD5FilePath);
//不存在
if (!fromMD5File.exists() || fromMD5File.length() == 0 || !fromMD5File.canRead() || fromMD5File.isDirectory()) {
//源文件是否存在
File fromFile = new File(fromFolderPath);
if (!fromFile.exists() || fromFile.length() == 0 || !fromFile.canRead()) {
result = CMD_RESULT_FROM_FILE_NONEXIST;
return result;
}
//生成源文件MD5文件夹
if (!(new File(fromMD5FolderPath).exists())) {
process = runtime.exec("mkdir -p " + fromMD5FolderPath);
process.waitFor();
}
//根据源文件生成MD5文件并保存
process = runtime.exec(new String[]{"sh","-c","find " + fromFolderPath +
" -type f -print0 | xargs -0 md5sum | sort > " + fromMD5FilePath});
result = process.waitFor();
Log.d(TAG, "frommd5 result=" + result);
}
//源文件MD5文件可用,开始比较
if (result == 0 && new File(fromMD5FilePath).length() > 0) {
Log.d(TAG, "frommd5 completed " + fromFolderPath);
String fromMD5String = readFileContentStr(fromMD5FilePath);
String toMD5String = readFileContentStr(toMD5FilePath);
if (fromMD5String.equals(toMD5String)){
Log.d(TAG,"md5 is same");
}else {
result = CMD_RESULT_FILE_NONSAME;
Log.d(TAG,"md5 is not same");
}
} else {
//生成异常,删除
deleteFolderOrFile(fromMD5FilePath);
Log.d(TAG, "frommd5 fail " + fromFolderPath);
}
} else {
//生成异常,删除
deleteFolderOrFile(toMD5FilePath);
Log.d(TAG, "tomd5 fail " + toFolderPath);
}
} catch (Exception e) {
Log.e(TAG, "getMD5 " + e.toString());
result = CMD_RESULT_UNKNOWN;
}
return result;
}
public static int createMD5File(String folderPath, String MD5FolderPath, String MD5FileName) {
Log.d(TAG, "createMD5File folderPath " + folderPath + " MD5FolderPath " + MD5FolderPath + "MD5FileName " + MD5FileName);
String MD5FilePath = MD5FolderPath + "/" + MD5FileName;
int result;
java.lang.Process process;
try {
Runtime runtime = Runtime.getRuntime();
//源文件是否存在
File fromFile = new File(folderPath);
if (!fromFile.exists() || fromFile.length() == 0 || !fromFile.canRead()) {
result = CMD_RESULT_FROM_FILE_NONEXIST;
return result;
}
//生成源文件MD5文件夹
if (!(new File(MD5FolderPath).exists())) {
process = runtime.exec("mkdir -p " + MD5FolderPath);
process.waitFor();
}
//根据源文件生成MD5文件并保存
process = runtime.exec(new String[]{"sh","-c","find " + folderPath +
" -type f -print0 | xargs -0 md5sum | sort > " + MD5FilePath});
result = process.waitFor();
Log.d(TAG, "createMD5File result=" + result);
} catch (Exception e) {
Log.e(TAG, "createMD5File " + e.toString());
result = CMD_RESULT_UNKNOWN;
}
return result;
}
public static String readFileContentStr(String fullFilename) {
StringBuffer readOutStr = new StringBuffer();
BufferedReader bufReader = null;
try {
bufReader = new BufferedReader(new FileReader(fullFilename));
String line = "";
while ((line = bufReader.readLine()) != null) {
readOutStr.append(line.substring(0,32));
}
Log.d("readFileContentStr", "Successfully to read out string from file " + fullFilename);
} catch (IOException e) {
e.printStackTrace();
Log.d("readFileContentStr", "Fail to read out string from file " + fullFilename);
} finally {
if (bufReader != null) {
try {
bufReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return readOutStr.toString();
}
}
- 布局
代码块
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/copy_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="导入导航离线数据和MD5文件"/>
<Button
android:id="@+id/md5_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="导航离线数据MD5校验"/>
<Button
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="删除导航离线数据和MD5文件"/>
<Button
android:id="@+id/md5_create_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="生成MD5文件至U盘"
android:visibility="gone"/>
<Button
android:id="@+id/md5_copy_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="导入MD5文件"
android:visibility="gone"/>
<Button
android:id="@+id/stop_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="强行停止退出"
android:visibility="gone"/>
<TextView
android:id="@+id/copy_text"
android:gravity="left|center_vertical"
android:layout_width="500dp"
android:layout_height="100dp"
android:textSize="30sp"
android:background="@android:color/white"
android:textColor="@android:color/black"/>
</LinearLayout>
- 第二种拷贝方式
代码块
public boolean copyFolder1(String oldPath, String newPath) {
try {
File newFile = new File(newPath);
if (!newFile.exists()) {
if (!newFile.mkdirs()) {
Log.e("--Method--", "copyFolder: cannot create directory.");
return false;
}
}
File oldFile = new File(oldPath);
String[] files = oldFile.list();
File temp;
for (String file : files) {
if (oldPath.endsWith(File.separator)) {
temp = new File(oldPath + file);
} else {
temp = new File(oldPath + File.separator + file);
}
if (temp.isDirectory()) { //如果是子文件夹
copyFolder(oldPath + "/" + file, newPath + "/" + file);
} else if (!temp.exists()) {
Log.e("--Method--", "copyFolder: oldFile not exist.");
return false;
} else if (!temp.isFile()) {
Log.e("--Method--", "copyFolder: oldFile not file.");
return false;
} else if (!temp.canRead()) {
Log.e("--Method--", "copyFolder: oldFile cannot read.");
return false;
} else {
FileInputStream fileInputStream = new FileInputStream(temp);
FileOutputStream fileOutputStream = new FileOutputStream(newPath + "/" + temp.getName());
byte[] buffer = new byte[1024];
int byteRead;
while ((byteRead = fileInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, byteRead);
}
fileInputStream.close();
fileOutputStream.flush();
fileOutputStream.close();
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}