Kaynağa Gözat

v1.0.2开发:优化权限申请永久拒绝后的弹窗逻辑

#Suyghur 2 yıl önce
ebeveyn
işleme
dc9f0b774b

+ 26 - 2
build.gradle

@@ -6,7 +6,6 @@ buildscript {
     ext {
         kotlin_version = '1.6.0'
     }
-
     repositories {
         google()
         mavenCentral()
@@ -14,14 +13,39 @@ buildscript {
         maven { url 'https://maven.aliyun.com/repository/public' }
         maven { url 'https://jitpack.io' }
     }
+    allprojects {
+        repositories {
+            google()
+            mavenCentral()
+            jcenter()
+            maven { url 'https://maven.aliyun.com/repository/public' }
+            maven { url 'https://jitpack.io' }
+        }
+    }
     dependencies {
-        classpath 'com.android.tools.build:gradle:7.0.4'
+        classpath 'com.android.tools.build:gradle:7.0.2'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
     }
 }
 
+allprojects{
+    repositories {
+        google()
+        mavenCentral()
+        jcenter()
+        maven {
+            allowInsecureProtocol = true
+            url 'https://maven.aliyun.com/repository/public'
+        }
+        maven {
+            allowInsecureProtocol = true
+            url 'https://jitpack.io'
+        }
+    }
+}
+
 task clean(type: Delete) {
     delete rootProject.buildDir
 }

+ 1 - 1
gradle.properties

@@ -18,4 +18,4 @@ android.useAndroidX=true
 # Kotlin code style for this project: "official" or "obsolete":
 kotlin.code.style=official
 org.gradle.parallel=true
-org.gradle.configureondemand=true
+org.gradle.configureondemand=true

+ 2 - 2
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Mon Jan 10 14:11:04 CST 2022
+#Tue Jan 11 16:22:22 CST 2022
 distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
 distributionPath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME

+ 31 - 5
library_support/proguard-rules.pro

@@ -41,11 +41,23 @@
 -keepattributes *Annotation*
 -keepattributes *JavascriptInterface*
 
-# 保留内部类
--keepattributes Exceptions,InnerClasses
+# keep javascript注释的方法,使用到webview js回调方法的需要添加此配置
+-keepclassmembers class * {
+    @android.webkit.JavascriptInterface <methods>;
+}
+
+#  #保留内部接口或内部类、内部类、泛型签名类型
+-keepattributes Exceptions,InnerClasses,Signature
+
+# 将崩溃日志文件来源重命名为"SourceFile"
+-renamesourcefileattribute SourceFile
+# 产生有用的混淆堆栈跟踪
+-keepattributes SourceFile,LineNumberTable
+# 保留注释
+-keepattributes *Annotation*
 
-# 保留泛型
--keepattributes Signature
+# 保留函数的参数名
+-keepparameternames
 
 -keepnames class * implements java.io.Serializable
 -keepclassmembers class * implements java.io.Serializable {
@@ -111,7 +123,19 @@
 
 -keep class **JNI* {*;}
 
--keep class android.support.annotation.**{*;}
+# 保留native方法
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+# keep R文件的静态字段
+-keepclassmembers class **.R$* {
+    public static <fields>;
+}
+
+
+-keeppackagenames cn.yyxx.support.**
+
 -keep class cn.yyxx.support.AndroidBug5497Workaround{ public <fields>;public <methods>;}
 -keep class cn.yyxx.support.AppUtils{ public <fields>;public <methods>;}
 -keep class cn.yyxx.support.BeanUtils{ public <fields>;public <methods>;}
@@ -138,5 +162,7 @@
 -keep class cn.yyxx.support.permission.Permission$Group{ *;}
 -keep class cn.yyxx.support.permission.PermissionKitActivity{  public <fields>; public <methods>;}
 -keep class cn.yyxx.support.permission.IPermissionCallback{  public <fields>; public <methods>;}
+-keep class cn.yyxx.support.permission.IPermissionInterceptor{  public <fields>; public <methods>;}
+
 
 

+ 7 - 2
library_support/src/main/java/cn/yyxx/support/AppUtils.java

@@ -2,11 +2,10 @@ package cn.yyxx.support;
 
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.text.TextUtils;
-import android.widget.TextView;
 
 import java.util.List;
 
@@ -129,4 +128,10 @@ public class AppUtils {
         }
         return true;
     }
+
+
+    public static boolean isLandscape(Context context) {
+        int orientation = context.getResources().getConfiguration().orientation;
+        return orientation == Configuration.ORIENTATION_LANDSCAPE;
+    }
 }

+ 1 - 3
library_support/src/main/java/cn/yyxx/support/permission/BasePermissionInterceptor.java

@@ -9,8 +9,6 @@ import android.widget.Toast;
 import java.util.ArrayList;
 import java.util.List;
 
-import cn.yyxx.support.hawkeye.LogUtils;
-
 /**
  * @author #Suyghur.
  * Created on 2021/10/31
@@ -31,7 +29,7 @@ public class BasePermissionInterceptor implements IPermissionInterceptor {
 
     @Override
     public void deniedPermissions(FragmentActivity activity, List<String> permissions, boolean never, IPermissionCallback callback) {
-        if (never) {
+        if (never && PermissionKit.enablePermissionDialog) {
             showPermissionDialog(activity, permissions);
             return;
         }

+ 2 - 1
library_support/src/main/java/cn/yyxx/support/permission/PermissionKit.java

@@ -5,7 +5,6 @@ import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.support.v4.app.FragmentActivity;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -24,6 +23,8 @@ public final class PermissionKit {
      */
     public static final int REQUEST_CODE = 1024 + 1;
 
+    public static boolean enablePermissionDialog = true;
+
     /**
      * 权限请求拦截器
      */

+ 196 - 0
library_support/src/main/java/cn/yyxx/support/volley/MultipartRequest.java

@@ -0,0 +1,196 @@
+package cn.yyxx.support.volley;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import cn.yyxx.support.hawkeye.LogUtils;
+import cn.yyxx.support.volley.entity.FileEntity;
+import cn.yyxx.support.volley.source.AuthFailureError;
+import cn.yyxx.support.volley.source.NetworkResponse;
+import cn.yyxx.support.volley.source.ParseError;
+import cn.yyxx.support.volley.source.Request;
+import cn.yyxx.support.volley.source.Response;
+import cn.yyxx.support.volley.source.toolbox.HttpHeaderParser;
+
+/**
+ * @author #Suyghur.
+ * Created on 2022/01/11
+ */
+public class MultipartRequest extends Request<String> {
+
+    private final String MULTIPART_FORM_DATA = "multipart/form-data"; // 数据类型
+    private final String BOUNDARY = "---------" + UUID.randomUUID().toString(); // 随机生成边界分隔线
+    private final String NEW_LINE = "\r\n"; // 换行符
+
+    private Map<String, Object> mParams;
+    private List<FileEntity> mFileEntityList;
+    private FileEntity mFileEntity;
+    private Response.Listener<String> mListener;
+    private Charset mCharSet;
+
+    private boolean isSingleFile = false;
+
+    public MultipartRequest(String url, Map<String, Object> params, Charset charSet, List<FileEntity> fileEntityList, Response.Listener<String> listener, Response.ErrorListener errorListener) {
+        super(Method.POST, url, errorListener);
+        this.mParams = params;
+        this.mCharSet = charSet;
+        this.mFileEntityList = fileEntityList;
+        this.mListener = listener;
+        this.isSingleFile = false;
+    }
+
+    public MultipartRequest(String url, Map<String, Object> params, Charset charSet, FileEntity fileEntity, Response.Listener<String> listener, Response.ErrorListener errorListener) {
+        super(Method.POST, url, errorListener);
+        this.mParams = params;
+        this.mCharSet = charSet;
+        this.mFileEntity = fileEntity;
+        this.mListener = listener;
+        this.isSingleFile = true;
+    }
+
+    public MultipartRequest(String url, Map<String, Object> params, List<FileEntity> fileEntityList, Response.Listener<String> listener, Response.ErrorListener errorListener) {
+        this(url, params, Charset.defaultCharset(), fileEntityList, listener, errorListener);
+    }
+
+    public MultipartRequest(String url, Map<String, Object> params, FileEntity fileEntity, Response.Listener<String> listener, Response.ErrorListener errorListener) {
+        this(url, params, Charset.defaultCharset(), fileEntity, listener, errorListener);
+    }
+
+
+    @Override
+    protected Response<String> parseNetworkResponse(NetworkResponse response) {
+        try {
+            return Response.success(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), HttpHeaderParser.parseCacheHeaders(response));
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return Response.error(new ParseError(e));
+        }
+    }
+
+    @Override
+    protected void deliverResponse(String response) {
+        mListener.onResponse(response);
+    }
+
+    @Override
+    public byte[] getBody() throws AuthFailureError {
+        if (isSingleFile) { // 单文件上传
+            return singleFileUp();
+        } else { // 多个文件上传
+            return multipleFileUp();
+        }
+    }
+
+    /**
+     * 多个文件上传
+     */
+    private byte[] multipleFileUp() throws AuthFailureError {
+        if ((mParams == null || mParams.size() <= 0) && (mFileEntityList == null || mFileEntityList.size() <= 0)) {
+            // 没有参数也没有文件
+            return super.getBody();
+        } else {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            if (mParams != null && mParams.size() > 0) {
+                // 有参数,先拼接参数
+                paramsFormat(bos);
+            }
+            if (mFileEntityList != null && mFileEntityList.size() > 0) {
+                // 有文件,提交文件
+                for (FileEntity fileEntity : mFileEntityList) {
+                    fileFormat(bos, fileEntity);
+                }
+            }
+            // 所有参数拼接完成,拼接结束行
+            endLine(bos);
+            return bos.toByteArray();
+        }
+    }
+
+    /**
+     * 单个文件上传
+     */
+    private byte[] singleFileUp() throws AuthFailureError {
+        if ((mParams == null || mParams.size() <= 0) && (mFileEntity == null)) {
+            // 没有参数也没有文件
+            return super.getBody();
+        } else {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            if (mParams != null && mParams.size() > 0) {
+                // 有参数,先拼接参数
+                paramsFormat(bos);
+            }
+            if (mFileEntity != null) {
+                // 有文件,提交文件
+                fileFormat(bos, mFileEntity);
+            }
+            // 所有参数拼接完成,拼接结束行
+            endLine(bos);
+            return bos.toByteArray();
+        }
+    }
+
+    /**
+     * 结束行内容
+     */
+    private void endLine(ByteArrayOutputStream bos) {
+        String endLine = "--" + BOUNDARY + "--" + NEW_LINE;
+        try {
+            bos.write(endLine.getBytes(mCharSet));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 格式化上传文件格式
+     */
+    private void fileFormat(ByteArrayOutputStream bos, FileEntity fileEntity) {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("--").append(BOUNDARY).append(NEW_LINE);
+        stringBuilder.append("Content-Disposition: form-data; name=\"").append(fileEntity.mName).append("\"").append(";filename=\"").append(fileEntity.mFileName).append("\"").append(NEW_LINE);
+        stringBuilder.append("Content-Type: ").append(fileEntity.mMime).append(";charset=").append(mCharSet).append(NEW_LINE);
+        stringBuilder.append(NEW_LINE);
+        try {
+            bos.write(stringBuilder.toString().getBytes(mCharSet));
+            bos.write(fileEntity.getFileBytes());
+            bos.write(NEW_LINE.getBytes(mCharSet));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 格式化上传参数格式
+     */
+    private void paramsFormat(ByteArrayOutputStream bos) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (String key : mParams.keySet()) {
+            Object value = mParams.get(key);
+            stringBuilder.append("--").append(BOUNDARY).append(NEW_LINE);
+            stringBuilder.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(NEW_LINE);
+            stringBuilder.append(NEW_LINE);
+            stringBuilder.append(value).append(NEW_LINE);
+        }
+        LogUtils.d(stringBuilder.toString());
+        try {
+            bos.write(stringBuilder.toString().getBytes(mCharSet));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 返回头信息,用于指定上传的内容类型
+     */
+    @Override
+    public String getBodyContentType() {
+        // 如果参数和文件都为null时,不会执行这个方法
+        // Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryS4nmHw9nb2Eeusll
+        return MULTIPART_FORM_DATA + ";boundary=" + BOUNDARY;
+    }
+}

+ 73 - 0
library_support/src/main/java/cn/yyxx/support/volley/entity/FileEntity.java

@@ -0,0 +1,73 @@
+package cn.yyxx.support.volley.entity;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * @author #Suyghur.
+ * Created on 2022/01/11
+ */
+public class FileEntity {
+    /**
+     * 参数名称
+     */
+    public String mName;
+    /**
+     * 上传的文件名
+     */
+    public String mFileName;
+    /**
+     * 需要上传的文件
+     */
+    public File mFile;
+    /**
+     * 文件的 mime,需要根据文档查询<br/>
+     * 默认使用 application/octet-stream  任意的二进制数据
+     */
+    public String mMime = "application/octet-stream";
+
+    public FileEntity() {
+    }
+
+    public FileEntity(String mName, String mFileName, File mFile, String mMime) {
+        this.mName = mName;
+        this.mFileName = mFileName;
+        this.mFile = mFile;
+        this.mMime = mMime;
+    }
+
+    public byte[] getFileBytes() {
+        FileInputStream fileInputStream = null;
+        ByteArrayOutputStream outputStream = null;
+        try {
+            fileInputStream = new FileInputStream(mFile);
+            outputStream = new ByteArrayOutputStream();
+            int len;
+            byte[] bytes = new byte[1024];
+            while ((len = fileInputStream.read(bytes)) != -1) {
+                outputStream.write(bytes, 0, len);
+            }
+            return outputStream.toByteArray();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (fileInputStream != null) {
+                try {
+                    fileInputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return null;
+    }
+}

+ 1 - 18
settings.gradle

@@ -1,22 +1,5 @@
-dependencyResolutionManagement {
-    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
-    repositories {
-        google()
-        mavenCentral()
-        jcenter()
-        maven {
-            allowInsecureProtocol = true
-            url 'https://maven.aliyun.com/repository/public'
-        }
-        maven {
-            allowInsecureProtocol = true
-            url 'https://jitpack.io'
-        }
-    }
-}
 rootProject.name = 'YYXXSupportSdk'
 include ':demo'
 include ':library_support'
 include ':library_volleyx'
-include ':library_volley'
-
+include ':library_volley'