Преглед изворни кода

增加MyLog本地缓存日志,自动更新增加权限和分区处理功能

songw пре 3 месеци
родитељ
комит
025f5580c7

+ 118 - 0
app/proguard-rules.pro

@@ -20,6 +20,124 @@
 # hide the original source file name.
 #-renamesourcefileattribute SourceFile
 
+## 对于一些基本指令的添加############################################### 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
+-optimizationpasses 5
+# 混合时不使用大小写混合,混合后的类名为小写
+-dontusemixedcaseclassnames
+# 指定不去忽略非公共库的类
+-dontskipnonpubliclibraryclasses
+# 这句话能够使我们的项目混淆后产生映射文件# 包含有类名->混淆后类名的映射关系
+-verbose
+# 指定不去忽略非公共库的类成员
+-dontskipnonpubliclibraryclassmembers
+# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
+-dontpreverify
+# 保留Annotation不混淆
+-keepattributes *Annotation*,InnerClasses
+# 避免混淆泛型
+-keepattributes Signature
+# 抛出异常时保留代码行号
+-keepattributes SourceFile,LineNumberTable
+# 指定混淆是采用的算法,后面的参数是一个过滤器
+# 这个过滤器是谷歌推荐的算法,一般不做更改
+-optimizations !code/simplification/cast,!field/*,!class/merging/*
+############################################### Android开发中一些需要保留的公共部分############################################### 保留我们使用的四大组件,自定义的Application等等这些类不被混淆# 因为这些子类都有可能被外部调用
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class * extends android.view.View
+
+# 保留support下的所有类及其内部类
+-dontwarn android.support.**
+-keep class android.support.** {*;}
+-dontwarn android.os.**
+-keep class android.os.** {*;}
+-dontwarn com.android.**
+-keep class com.android.** {*;}
+
+# 保留继承的
+-keep public class * extends android.support.v4.**
+-keep public class * extends android.support.v7.**
+-keep public class * extends android.support.annotation.**
+
+# 保留R下面的资源
+-keep class **.R$* {*;}
+
+# 保留本地native方法不被混淆
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+# 保留在Activity中的方法参数是view的方法,
+# 这样以来我们在layout中写的onClick就不会被影响
+-keepclassmembers class * extends android.app.Activity{
+    public void *(android.view.View);
+}
+# 保留枚举类不被混淆
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+# 保留我们自定义控件(继承自View)不被混淆
+-keep public class * extends android.view.View{
+    *** get*();
+    void set*(***);
+    public <init>(android.content.Context);
+    public <init>(android.content.Context, android.util.AttributeSet);
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+# 保留Parcelable序列化类不被混淆
+-keep class * implements android.os.Parcelable {
+    public static final android.os.Parcelable$Creator *;
+}
+# 保留Serializable序列化的类不被混淆
+-keepclassmembers class * implements java.io.Serializable {
+    static final long serialVersionUID;
+    private static final java.io.ObjectStreamField[] serialPersistentFields;
+    !static !transient <fields>;
+    !private <fields>;
+    !private <methods>;
+    private void writeObject(java.io.ObjectOutputStream);
+    private void readObject(java.io.ObjectInputStream);
+    java.lang.Object writeReplace();
+    java.lang.Object readResolve();
+}
+# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
+-keepclassmembers class * {
+    void *(**On*Event);
+}
+
+##3.webview
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+#-keepclassmembers class * extends android.webkit.webViewClient {
+#    public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+#    public boolean *(android.webkit.WebView, java.lang.String);
+#}
+#-keepclassmembers class * extends android.webkit.webViewClient {
+#    public void *(android.webkit.webView, jav.lang.String);
+#}
+
+#移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用
+#这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
+#-assumenosideeffects class android.util.Log {
+#    public static *** v(...);
+#    public static *** i(...);
+#    public static *** d(...);
+#    public static *** w(...);
+#    public static *** e(...);
+#}
+
+
 
 #友盟混淆
 -keep class com.umeng.** {*;}

+ 1 - 1
app/src/main/AndroidManifest.xml

@@ -86,7 +86,7 @@
         </activity>
         <service android:name="com.uas.equipment.webtcp.WebSocketService"
             />
-        <provider xmlns:tools="http://schemas.android.com/tools"
+        <provider
             android:name="android.support.v4.content.FileProvider"
             android:authorities="com.uas.equipment"
             android:exported="false"

+ 8 - 0
app/src/main/java/com/uas/equipment/application/PdaApplication.java

@@ -14,6 +14,7 @@ import com.facebook.stetho.Stetho;
 import com.uas.equipment.R;
 import com.uas.equipment.util.AndroidUtil;
 import com.uas.equipment.util.FakeX509TrustManager;
+import com.uas.equipment.util.MyLog;
 import com.uas.equipment.util.SoundUtil;
 import com.umeng.analytics.MobclickAgent;
 import com.umeng.commonsdk.UMConfigure;
@@ -89,6 +90,13 @@ public class PdaApplication extends Application {
 
         initUmeng();
 //        getMessageData();
+
+        //删除非当天的Log日志, Android8.0以下用不了
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            MyLog.delNotDayFile();
+        }else {
+            MyLog.isFileCreatedTodayDel();
+        }
     }
 
     private void initUmeng() {

+ 71 - 30
app/src/main/java/com/uas/equipment/fragment/VersionUpgradeFragment.java

@@ -1,16 +1,21 @@
 package com.uas.equipment.fragment;
 
+import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
+import android.support.annotation.RequiresApi;
 import android.support.v4.content.FileProvider;
 import android.text.TextUtils;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
@@ -25,16 +30,13 @@ import com.uas.equipment.util.FastjsonUtil;
 import com.uas.equipment.util.FileUtils;
 import com.uas.equipment.util.HttpCallback;
 import com.uas.equipment.util.HttpParams;
+import com.uas.equipment.util.MyLog;
 import com.uas.equipment.util.VollyRequest;
 import com.uas.equipment.util.down.CommonProgressPop;
 import com.uas.equipment.util.down.ProgressDownloader;
 import com.uas.equipment.util.down.ProgressResponseBody;
 
 import java.io.File;
-import java.io.IOException;
-
-import static com.uas.equipment.util.Constants.CONSTANT.APK_FILE_NAME;
-import static com.uas.equipment.util.Constants.CONSTANT.APK_FILE_PATH;
 
 
 /**
@@ -50,6 +52,8 @@ public class VersionUpgradeFragment extends BaseFragment implements ProgressResp
     private File file;
     private String mAttachId;
     private StringRequest mStringRequest;
+    private File apkFile;
+
     @Override
     protected int getLayout() {
         return R.layout.fragment_version_upgrade;
@@ -76,20 +80,9 @@ public class VersionUpgradeFragment extends BaseFragment implements ProgressResp
                 mProgressPop.showPopupWindow();
 
                 breakPoints = 0L;
-                File directory = new File(APK_FILE_PATH);
-                if (!directory.exists() && !directory.isDirectory()) {
-                    boolean mkdirs = directory.mkdirs();
-                } else {
-                    FileUtils.delAllFile(APK_FILE_PATH);
-                }
-                file = new File(APK_FILE_PATH, APK_FILE_NAME);
-                try {
-                    file.createNewFile();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
                 String downloadUrl = GloableParams.ADDRESS_COMMON_DOWNLOADBYID + "?id=" + mAttachId;
-                mDownloader = new ProgressDownloader(downloadUrl, file, VersionUpgradeFragment.this);
+                MyLog.e("aaa","下载路径为:" + downloadUrl);
+                mDownloader = new ProgressDownloader(downloadUrl, apkFile, VersionUpgradeFragment.this);
                 mDownloader.download(0L);
             }
         });
@@ -98,8 +91,65 @@ public class VersionUpgradeFragment extends BaseFragment implements ProgressResp
     @Override
     protected void initDatas() {
         mOldVersionTv.setText(AndroidUtil.getVersionName(mActivity));
-
         getNewVersionMsg();
+
+        //不同版本分区处理
+        String fileName = "update_" + "APP" + ".apk";
+        File downloadDir;
+        if (Build.VERSION.SDK_INT >= 29) {
+            // Android 10+ 使用私有目录
+            downloadDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
+        } else {
+            downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+        }
+        if (!downloadDir.exists()) {
+            downloadDir.mkdirs();
+        }else {
+            FileUtils.delAllFile(downloadDir.getAbsolutePath()+ fileName);
+        }
+
+        apkFile = new File(downloadDir, fileName);
+
+        //检查权限
+        if (Build.VERSION.SDK_INT >= 26) {
+            if (!isHasInstallPermissionWithO(getActivity())) {
+                startInstallPermissionSettingActivity(getActivity());
+            }
+        }
+    }
+
+    /**
+     * 检测是否拥有安装未知应用权限canRequestPackageInstalls
+     */
+    @RequiresApi(api = Build.VERSION_CODES.O)
+    private boolean isHasInstallPermissionWithO(Context context){
+        if (context == null){
+            return false;
+        }
+        return context.getPackageManager().canRequestPackageInstalls();
+    }
+
+    /**
+     * 如果没有权限,则申请安装未知应用权限(打开获取权限界面)
+     */
+    @RequiresApi(api = Build.VERSION_CODES.O)
+    private void startInstallPermissionSettingActivity(Context context) {
+        if (context == null) {
+            return;
+        }
+        Intent intent = new Intent();
+        //获取当前apk包URI,并设置到intent中(这一步设置,可让“未知应用权限设置界面”只显示当前应用的设置项)
+        Uri packageURI = Uri.parse("package:" + context.getPackageName());
+        intent.setData(packageURI);
+        //设置不同版本跳转未知应用的动作
+        if (Build.VERSION.SDK_INT >= 26) {
+            //intent = new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,packageURI);
+            intent.setAction(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
+        } else {
+            intent.setAction(android.provider.Settings.ACTION_SECURITY_SETTINGS);
+        }
+        ((Activity) context).startActivity(intent);
+        Toast.makeText(getActivity(), "请打开未知应用安装权限", Toast.LENGTH_SHORT).show();
     }
 
     private void getNewVersionMsg() {
@@ -208,15 +258,9 @@ public class VersionUpgradeFragment extends BaseFragment implements ProgressResp
                     public void onFail(int flag, String failStr) throws Exception {
                         progressDialog.dismiss();
                         CommonUtil.toastNoRepeat(mActivity, failStr);
-
                     }
-
                 });
 
-
-
-
-
     }
 
     @Override
@@ -265,17 +309,14 @@ public class VersionUpgradeFragment extends BaseFragment implements ProgressResp
                     CommonUtil.toastNoRepeat(mActivity, "下载完成");
                     mProgressPop.dismiss();
                     try {
-                        File apk = new File(APK_FILE_PATH, APK_FILE_NAME);
                         Intent intent = new Intent(Intent.ACTION_VIEW);
+                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                         if (Build.VERSION.SDK_INT >= 24) {
-                            Uri apkUri = FileProvider.getUriForFile(mActivity,
-                                    "com.uas.pda_smart_sa.fileprovider", apk);
-                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                            Uri apkUri = FileProvider.getUriForFile(mActivity, getActivity().getPackageName() +".fileprovider", apkFile);
                             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                             intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                         } else {
-                            intent.setDataAndType(Uri.fromFile(apk), "application/vnd.android.package-archive");
-                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
                         }
                         mActivity.startActivity(intent);
                     } catch (Exception e) {

+ 3 - 1
app/src/main/java/com/uas/equipment/util/CommonUtil.java

@@ -610,9 +610,11 @@ public class CommonUtil {
             if (errorMsg != null && errorMsg.exceptionInfo != null) {
                 errorStr = errorMsg.exceptionInfo;
             } else {
-                errorStr = "系统错误";
+                //errorStr = "系统错误";
+                errorStr = new String(volleyError.networkResponse.data);
             }
         }
+        MyLog.d("aaa","响应失败:" + errorStr);
         //振动提示
         makeNotice();
         /*MediaPlayer mp = new MediaPlayer();

+ 63 - 0
app/src/main/java/com/uas/equipment/util/FileUtils.java

@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.security.SecureRandom;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.util.Calendar;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.SSLContext;
@@ -423,4 +424,66 @@ public class FileUtils {
             return true;
         }
     }
+
+    /**
+     * 判断文件是否为当天创建(使用最后修改时间)
+     * Android 7.0推荐使用此方法
+     */
+    public static boolean isFileCreatedToday(File file) {
+        if (file == null || !file.exists()) {
+            return false;
+        }
+
+        // 获取文件的最后修改时间
+        long lastModified = file.lastModified();
+
+        // 获取当前时间的Calendar
+        Calendar today = Calendar.getInstance();
+
+        // 获取文件时间的Calendar
+        Calendar fileDate = Calendar.getInstance();
+        fileDate.setTimeInMillis(lastModified);
+
+        // 比较年、月、日是否相同
+        return today.get(Calendar.YEAR) == fileDate.get(Calendar.YEAR) &&
+                today.get(Calendar.MONTH) == fileDate.get(Calendar.MONTH) &&
+                today.get(Calendar.DAY_OF_MONTH) == fileDate.get(Calendar.DAY_OF_MONTH);
+    }
+
+    /**
+     * 获取文件创建时间的字符串表示
+     */
+    public static String getFileCreationTimeString(File file) {
+        if (file == null || !file.exists()) {
+            return "文件不存在";
+        }
+
+        long lastModified = file.lastModified();
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis(lastModified);
+
+        return String.format("%04d-%02d-%02d %02d:%02d:%02d",
+                cal.get(Calendar.YEAR),
+                cal.get(Calendar.MONTH) + 1, // 月份从0开始
+                cal.get(Calendar.DAY_OF_MONTH),
+                cal.get(Calendar.HOUR_OF_DAY),
+                cal.get(Calendar.MINUTE),
+                cal.get(Calendar.SECOND));
+    }
+
+    /**
+     * 格式化文件大小
+     */
+    public static String formatFileSize(long size) {
+        if (size < 1024) {
+            return size + " B";
+        } else if (size < 1024 * 1024) {
+            return String.format("%.2f KB", size / 1024.0);
+        } else if (size < 1024 * 1024 * 1024) {
+            return String.format("%.2f MB", size / (1024.0 * 1024));
+        } else {
+            return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
+        }
+    }
+
 }

+ 281 - 143
app/src/main/java/com/uas/equipment/util/MyLog.java

@@ -1,13 +1,26 @@
 package com.uas.equipment.util;
 
 import android.annotation.SuppressLint;
+import android.os.Build;
+import android.os.Environment;
+import android.support.annotation.RequiresApi;
 import android.util.Log;
 
+import com.uas.equipment.application.PdaApplication;
+
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
 import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Date;
 
 /**
@@ -15,147 +28,272 @@ import java.util.Date;
  */
 @SuppressLint("SimpleDateFormat")
 public class MyLog {
-	public static Boolean MYLOG_SWITCH = true; // 日志文件总开关
-	private static Boolean MYLOG_WRITE_TO_FILE = true;// 日志写入文件开关
-	private static char MYLOG_TYPE = 'v';// 输入日志类型,w代表只输出告警信息等,v代表输出所有信息
-	@SuppressLint("SdCardPath")
-	private static String MYLOG_PATH_SDCARD_DIR1 = "/sdcard/MSShow";    // 日志文件在sdcard中的路径
-	private static String MYLOG_PATH_SDCARD_DIR2 = "/Log";
-	private static String MYLOG_PATH_SDCARD_DIR = MYLOG_PATH_SDCARD_DIR1+MYLOG_PATH_SDCARD_DIR2;
-	private static String MYLOGFILEName = "Log.txt";// 本类输出的日志文件名称
-
-	@SuppressLint("SimpleDateFormat")
-	private static SimpleDateFormat myLogSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 日志的输出格式
-
-	private static boolean isDebug = true;		//普通log的开关
-	private static String TAG = "我的天啊" +"-----------";
-
-	public static void e(String msg){
-		if(isDebug){
-			Log.e(TAG, msg);
-		}
-	}
-
-	public static void w(String msg){
-		if(isDebug){
-			Log.w(TAG, msg);
-		}
-	}
-
-	public static void d(String msg){
-		if(isDebug){
-			Log.d(TAG, msg);
-		}
-	}
-
-	public static void i(String msg){
-		if(isDebug){
-			Log.i(TAG, msg);
-		}
-	}
-
-	public static void w(String tag, Object msg) { // 警告信息
-		log(tag, msg.toString(), 'w');
-	}
-
-	public static void e(String tag, Object msg) { // 错误信息
-		log(tag, msg.toString(), 'e');
-	}
-
-	public static void d(String tag, Object msg) {// 调试信息
-		log(tag, msg.toString(), 'd');
-	}
-
-	public static void i(String tag, Object msg) {//
-		log(tag, msg.toString(), 'i');
-	}
-
-	public static void v(String tag, Object msg) {
-		log(tag, msg.toString(), 'v');
-	}
-
-	public static void w(String tag, String text) {
-		log(tag, text, 'w');
-	}
-
-	public static void e(String tag, String text) {
-		log(tag, text, 'e');
-	}
-
-	public static void d(String tag, String text) {
-		log(tag, text, 'd');
-	}
-
-	public static void i(String tag, String text) {
-		log(tag, text, 'i');
-	}
-
-	public static void v(String tag, String text) {
-		log(tag, text, 'v');
-	}
-
-	/**
-	 * 根据tag, msg和等级,输出日志
-	 */
-	private static void log(String tag, String msg, char level) {
-		msg = "\r\n"+msg;
-		if (MYLOG_SWITCH) {
-			if ('e' == level && ('e' == MYLOG_TYPE || 'v' == MYLOG_TYPE)) { // 输出错误信息
-				Log.e(tag, msg);
-			} else if ('w' == level && ('w' == MYLOG_TYPE || 'v' == MYLOG_TYPE)) {
-				Log.w(tag, msg);
-			} else if ('d' == level && ('d' == MYLOG_TYPE || 'v' == MYLOG_TYPE)) {
-				Log.d(tag, msg);
-			} else if ('i' == level && ('d' == MYLOG_TYPE || 'v' == MYLOG_TYPE)) {
-				Log.i(tag, msg);
-			} else {
-				Log.v(tag, msg);
-			}
-			if (MYLOG_WRITE_TO_FILE) {
-				writeLogtoFile(String.valueOf(level), tag, msg);
-			}
-		}
-	}
-
-	/**
-	 * 打开日志文件并写入日志
-	 * **/
-	private static void writeLogtoFile(String mylogtype, String tag, String text) {// 新建或打开日志文件
-		isExist(MYLOG_PATH_SDCARD_DIR1);
-		isExist(MYLOG_PATH_SDCARD_DIR);
-		Date nowtime = new Date();
-//		String needWriteFiel = logfile.format(nowtime);
-		String needWriteMessage = myLogSdf.format(nowtime) + "    " + mylogtype
-				+ "    " + tag + "    " + text;
-		File file = new File(MYLOG_PATH_SDCARD_DIR, MYLOGFILEName);
-		try {
-			FileWriter filerWriter = new FileWriter(file, true);// 后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
-			BufferedWriter bufWriter = new BufferedWriter(filerWriter);
-			bufWriter.write(needWriteMessage);
-			bufWriter.newLine();
-			bufWriter.close();
-			filerWriter.close();
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * 删除制定的日志文件
-	 * */
-	public static void delFile() {// 删除日志文件
-		File file = new File(MYLOG_PATH_SDCARD_DIR, MYLOGFILEName);
-		if (file.exists()) {
-			file.delete();
-		}
-	}
-
-	public static void isExist(String path) {
-		File file = new File(path);
-		// 判断文件夹是否存在,如果不存在则创建文件夹
-		if (!file.exists()) {
-			file.mkdir();
-		}
-
-	}
+    public static Boolean MYLOG_SWITCH = true; // 日志文件总开关
+    private static Boolean MYLOG_WRITE_TO_FILE = true;// 日志写入文件开关
+    private static char MYLOG_TYPE = 'v';// 输入日志类型,w代表只输出告警信息等,v代表输出所有信息
+    @SuppressLint("SdCardPath")
+//    private static String MYLOG_PATH_SDCARD_DIR1 = "/sdcard/MSShow";    // 日志文件在sdcard中的路径
+//    private static String MYLOG_PATH_SDCARD_DIR1 = "/data/data/" + PdaApplication.getmContext().getPackageName();  //APP包下创建的文件不需要权限
+    private static String MYLOG_PATH_SDCARD_DIR1 = "/sdcard/Android/data/" + PdaApplication.getmContext().getPackageName();  //模拟器的APP包下创建的文件
+    private static String MYLOG_PATH_SDCARD_DIR2 = "/Log";
+    private static String MYLOG_PATH_SDCARD_DIR = MYLOG_PATH_SDCARD_DIR1 + MYLOG_PATH_SDCARD_DIR2;
+    private static String MYLOGFILEName = "Log.txt";// 本类输出的日志文件名称
+
+    @SuppressLint("SimpleDateFormat")
+    private static SimpleDateFormat myLogSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 日志的输出格式
+
+    private static boolean isDebug = true;        //普通log的开关
+    private static String TAG = "英唐" + "-----------";
+
+    private static volatile MyLog myLog; // 使用 volatile 关键字确保多线程环境下的可见性
+
+    private MyLog() {
+    }
+
+    public static MyLog getInstance() {
+        if (myLog == null) { // 第一次检查,提高效率,避免每次都进行同步
+            synchronized (MyLog.class) { // 同步代码块,保证线程安全
+                if (myLog == null) { // 第二次检查,防止多个线程同时进入同步块时重复创建实例
+                    myLog = new MyLog();
+                    //兼容不同版本分区处理
+                    File downloadDir = null;
+                    if (Build.VERSION.SDK_INT >= 29) {
+                        // Android 10+ 使用私有目录
+                        downloadDir = PdaApplication.getmContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
+                    } else {
+                        downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+                    }
+                    if (!downloadDir.exists()) {
+                        downloadDir.mkdirs();
+                    }
+                    MYLOG_PATH_SDCARD_DIR1 = downloadDir.getAbsolutePath() + File.separator + PdaApplication.getmContext().getPackageName();
+
+                    //Log.e("aaa", "MyLog被创建了: " + MYLOG_PATH_SDCARD_DIR1);
+                }
+            }
+        }
+        return myLog;
+    }
+
+    public static void e(String msg) {
+        if (isDebug) {
+            Log.e(TAG, msg);
+        }
+    }
+
+    public static void w(String msg) {
+        if (isDebug) {
+            Log.w(TAG, msg);
+        }
+    }
+
+    public static void d(String msg) {
+        if (isDebug) {
+            Log.d(TAG, msg);
+        }
+    }
+
+    public static void i(String msg) {
+        if (isDebug) {
+            Log.i(TAG, msg);
+        }
+    }
+
+    public static void w(String tag, Object msg) { // 警告信息
+        log(tag, msg.toString(), 'w');
+    }
+
+    public static void e(String tag, Object msg) { // 错误信息
+        log(tag, msg.toString(), 'e');
+    }
+
+    public static void d(String tag, Object msg) {// 调试信息
+        log(tag, msg.toString(), 'd');
+    }
+
+    public static void i(String tag, Object msg) {//
+        log(tag, msg.toString(), 'i');
+    }
+
+    public static void v(String tag, Object msg) {
+        log(tag, msg.toString(), 'v');
+    }
+
+    public static void w(String tag, String text) {
+        log(tag, text, 'w');
+    }
+
+    public static void e(String tag, String text) {
+        log(tag, text, 'e');
+    }
+
+    public static void d(String tag, String text) {
+        log(tag, text, 'd');
+    }
+
+    public static void i(String tag, String text) {
+        log(tag, text, 'i');
+    }
+
+    public static void v(String tag, String text) {
+        log(tag, text, 'v');
+    }
+
+    /**
+     * 根据tag, msg和等级,输出日志
+     */
+    private static void log(String tag, String msg, char level) {
+        msg = "\r\n" + msg;
+        if (MYLOG_SWITCH) {
+            setInterceptlength(tag, msg, level);
+            if (MYLOG_WRITE_TO_FILE && 'd' == level) {
+                writeLogtoFile(String.valueOf(level), tag, msg);
+            }
+        }
+    }
+
+    public static void setInterceptlength(String tag, String msg,char level) {
+        if (msg.length() > 3000) {
+            // 因为Logcat一次最多能输出4000个字符左右,所以按3000字符分段比较好
+            int chunkCount = msg.length() / 3000; // 分割成多少段
+            for (int i = 0; i <= chunkCount; i++) {
+                int max = 3000 * (i + 1);
+                if (max >= msg.length()) {
+                    if ('e' == level) { // 输出错误信息
+                        Log.e(tag, msg.substring(3000 * i));
+                    } else if ('w' == level) {
+                        Log.w(tag, msg.substring(3000 * i));
+                    } else if ('d' == level) {
+                        Log.d(tag, msg.substring(3000 * i));
+                    } else if ('i' == level) {
+                        Log.i(tag, msg.substring(3000 * i));
+                    } else {
+                        Log.v(tag, msg.substring(3000 * i));
+                    }
+                } else {
+                    if ('e' == level) {
+                        Log.e(tag, msg.substring(3000 * i, max));
+                    } else if ('w' == level) {
+                        Log.w(tag, msg.substring(3000 * i, max));
+                    } else if ('d' == level) {
+                        Log.d(tag, msg.substring(3000 * i, max));
+                    } else if ('i' == level) {
+                        Log.i(tag, msg.substring(3000 * i, max));
+                    } else {
+                        Log.v(tag, msg.substring(3000 * i, max));
+                    }
+                }
+            }
+        } else {
+            if ('e' == level) {
+                Log.e(tag, msg);
+            } else if ('w' == level) {
+                Log.w(tag, msg);
+            } else if ('d' == level) {
+                Log.d(tag, msg);
+            } else if ('i' == level) {
+                Log.i(tag, msg);
+            } else {
+                Log.v(tag, msg);
+            }
+        }
+    }
+
+    /**
+     * 打开日志文件并写入日志,
+     **/
+    private static void writeLogtoFile(String mylogtype, String tag, String text) {
+    	// 新建或打开日志文件
+        isExist(MYLOG_PATH_SDCARD_DIR1);
+        isExist(MYLOG_PATH_SDCARD_DIR);
+        Date nowtime = new Date();
+        //		String needWriteFiel = logfile.format(nowtime);
+        String needWriteMessage = myLogSdf.format(nowtime) + "    " + mylogtype
+                + "    " + tag + "    " + text;
+        File file = new File(MYLOG_PATH_SDCARD_DIR, MYLOGFILEName);
+        try {
+            FileWriter filerWriter = new FileWriter(file, true);// 后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
+            BufferedWriter bufWriter = new BufferedWriter(filerWriter);
+            bufWriter.write(needWriteMessage);
+            bufWriter.newLine();
+            bufWriter.close();
+            filerWriter.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 删除制定的日志文件
+     */
+    public static void delFile() {// 删除日志文件
+        File file = new File(MYLOG_PATH_SDCARD_DIR, MYLOGFILEName);
+        if (file.exists()) {
+            file.delete();
+        }
+    }
+
+    public static void isExist(String path) {
+        File file = new File(path);
+        // 判断文件夹是否存在,如果不存在则创建文件夹
+        if (!file.exists()) {
+            file.mkdir();
+        }
+    }
+
+    /**
+     * 取消Android8.0的提示限制
+     */
+    @RequiresApi(api = Build.VERSION_CODES.O)
+    public static void delNotDayFile(){
+        File fileP = new File(MYLOG_PATH_SDCARD_DIR, MYLOGFILEName);
+        if (fileP.exists()) {
+            Path path = Paths.get(MYLOG_PATH_SDCARD_DIR + "/" + MYLOGFILEName); //文件路径
+            try {
+                // 获取文件的属性
+                BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
+                // 获取文件的创建时间
+                FileTime creationTime = attrs.creationTime();
+                // 转换为LocalDateTime以便于比较
+                //将FileTime对象转换为LocalDateTime以便于与当前日期进行比较。这里使用了系统的默认时区(ZoneId.systemDefault())。如果需要特定时区,可以替换为相应的ZoneId。
+                //通过LocalDateTime 的 toLocalDate()方法将时间转换为仅包含日期(忽略时间),然后与当前日期进行比较。
+                LocalDateTime creationDateTime = creationTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+                LocalDateTime now = LocalDateTime.now();
+
+                // 比较是否为当天创建
+                if (isToday(creationDateTime)) {
+                    //System.out.println("文件是今天创建的。");
+                } else {
+                    //System.out.println("文件不是今天创建的。");
+                    delFile();  //删除不是当天日期
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    // 辅助方法,检查日期是否为今天
+    @RequiresApi(api = Build.VERSION_CODES.O)
+    private static boolean isToday(LocalDateTime dateTime) {
+        LocalDate today = LocalDate.now();
+        LocalDate fileDate = dateTime.toLocalDate();
+        return today.equals(fileDate);
+    }
+
+    /**
+     * 判断文件是否为当天创建(使用最后修改时间),不同则删除
+     * Android 7.0推荐使用此方法
+     */
+    public static void isFileCreatedTodayDel() {
+        File fileP = new File(MYLOG_PATH_SDCARD_DIR, MYLOGFILEName);
+        if (fileP.exists()) {
+            if (!FileUtils.isFileCreatedToday(fileP)) {
+                delFile();  //删除不是当天创建的日期
+            }
+        }
+    }
+
+
+
 }

+ 2 - 2
app/src/main/java/com/uas/equipment/util/VolleyRequest.java

@@ -98,7 +98,7 @@ public class VolleyRequest {
                 index++;
             }
         }
-
+        MyLog.d("aaa","*************************" + "\n" + "接口地址:" + url);
         PdaApplication.mRequestQueue.cancelAll(httpParams.getUrl());
 
         stringRequest = new StringRequest(httpParams.getMethod(), url,
@@ -106,7 +106,7 @@ public class VolleyRequest {
                     @Override
                     public void onResponse(String s) {
                         try {
-                            LogUtil.prinlnLongMsg("responseSucc", s);
+                            MyLog.d("aaa","响应成功:" + s);
                             httpCallback.onSuccess(httpParams.getFlag(), s);
                         } catch (Exception e) {
                             e.printStackTrace();

+ 2 - 2
app/src/main/java/com/uas/equipment/util/VollyRequest.java

@@ -91,7 +91,7 @@ public class VollyRequest {
                 index++;
             }
         }
-
+        MyLog.d("aaa","*************************" + "\n" + "接口地址:" + url);
         PdaApplication.mRequestQueue.cancelAll(httpParams.getUrl());
 
         stringRequest = new StringRequest(httpParams.getMethod(), url,
@@ -99,7 +99,7 @@ public class VollyRequest {
                     @Override
                     public void onResponse(String s) {
                         try {
-                            LogUtil.prinlnLongMsg("responseSucc", s);
+                            MyLog.d("aaa","响应成功:" + s);
                             httpCallback.onSuccess(httpParams.getFlag(), s);
                         } catch (Exception e) {
                             e.printStackTrace();

+ 28 - 2
app/src/main/res/xml/file_paths.xml

@@ -1,9 +1,35 @@
 <?xml version="1.0" encoding="utf-8"?>
-<paths xmlns:android="http://schemas.android.com/apk/res/android">
+<!--<paths xmlns:android="http://schemas.android.com/apk/res/android">
     <external-path
         name="files_root"        path="Android/data/com.uas.equipment/" />
 
     <external-path
         name="external_storage_root"
         path="." />
-</paths>
+</paths>-->
+<paths>
+<!-- 外部存储根目录 -->
+<external-path
+    name="external"
+    path="." />
+
+<!-- 下载目录 -->
+<external-path
+    name="download"
+    path="Download" />
+
+<!-- 应用私有目录 -->
+<external-files-path
+    name="files"
+    path="." />
+
+<!-- 缓存目录 -->
+<external-cache-path
+    name="cache"
+    path="." />
+
+<!-- 内部存储目录 -->
+<files-path
+    name="internal"
+    path="." />
+</paths>