From bb68311167fb120d67020029a8481451d8791f49 Mon Sep 17 00:00:00 2001 From: lesterli2010 Date: Wed, 8 Jul 2020 19:55:48 -0700 Subject: [PATCH] Add image compress functionality --- app/build.gradle | 1 + .../sdk/im/qunar/com/qtalksdkdemo/Base64.java | 314 ++++++++++++++++ .../qunar/com/qtalksdkdemo/MainActivity.java | 33 +- .../im/qunar/com/qtalksdkdemo/UserInfo.java | 7 + .../permission/AbsPermissionTask.java | 29 ++ .../qtalksdkdemo/permission/DialogAlert.java | 110 ++++++ .../permission/IPermissionDialogDeploy.java | 22 ++ .../permission/OnPermissionListener.java | 31 ++ .../permission/PermissionAudio.java | 33 ++ .../permission/PermissionCamera.java | 33 ++ .../permission/PermissionContacts.java | 33 ++ .../permission/PermissionFragment.java | 147 ++++++++ .../permission/PermissionLocation.java | 33 ++ .../permission/PermissionOptional.java | 78 ++++ .../permission/PermissionReadPhoneState.java | 48 +++ .../permission/PermissionStorage.java | 34 ++ .../permission/PermissionTask.java | 47 +++ .../qtalksdkdemo/permission/PermissionX.java | 270 ++++++++++++++ build.gradle | 2 +- imsdk/build.gradle | 2 + .../qunar/im/ui/activity/PbChatActivity.java | 54 ++- .../util/easyphoto/easyphotos/EasyPhotos.java | 4 +- .../easyphoto/easyphotos/setting/Setting.java | 2 +- .../easyphotos/ui/EasyPhotosActivity.java | 245 +++++++------ .../easyphotos/ui/PreviewActivity.java | 57 +-- .../main/res/layout/activity_easy_photos.xml | 48 ++- .../layout/activity_preview_easy_photos.xml | 8 +- .../com/qunar/im/base/common/QChatRSA.java | 334 +++++++++++++++++- 28 files changed, 1869 insertions(+), 190 deletions(-) create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/Base64.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/UserInfo.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/AbsPermissionTask.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/DialogAlert.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/IPermissionDialogDeploy.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/OnPermissionListener.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionAudio.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionCamera.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionContacts.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionFragment.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionLocation.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionOptional.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionReadPhoneState.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionStorage.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionTask.java create mode 100644 app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionX.java diff --git a/app/build.gradle b/app/build.gradle index d6f476b..7fbdc02 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -112,5 +112,6 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.0.0' testImplementation 'junit:junit:4.12' + implementation "com.yanzhenjie.permission:support:2.0.1" implementation project(':imsdk')//implementation 'com.startalk.im:sdk-im:3.0.7' } diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/Base64.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/Base64.java new file mode 100644 index 0000000..a8996d1 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/Base64.java @@ -0,0 +1,314 @@ +package sdk.im.qunar.com.qtalksdkdemo; + +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; + +public final class Base64 { + + private static final int BASELENGTH = 128; + private static final int LOOKUPLENGTH = 64; + private static final int TWENTYFOURBITGROUP = 24; + private static final int EIGHTBIT = 8; + private static final int SIXTEENBIT = 16; + private static final int FOURBYTE = 4; + private static final int SIGN = -128; + private static char PAD = '='; + private static byte[] base64Alphabet = new byte[BASELENGTH]; + private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; + + static { + for (int i = 0; i < BASELENGTH; ++i) { + base64Alphabet[i] = -1; + } + for (int i = 'Z'; i >= 'A'; i--) { + base64Alphabet[i] = (byte) (i - 'A'); + } + for (int i = 'z'; i >= 'a'; i--) { + base64Alphabet[i] = (byte) (i - 'a' + 26); + } + + for (int i = '9'; i >= '0'; i--) { + base64Alphabet[i] = (byte) (i - '0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + + for (int i = 0; i <= 25; i++) { + lookUpBase64Alphabet[i] = (char) ('A' + i); + } + + for (int i = 26, j = 0; i <= 51; i++, j++) { + lookUpBase64Alphabet[i] = (char) ('a' + j); + } + + for (int i = 52, j = 0; i <= 61; i++, j++) { + lookUpBase64Alphabet[i] = (char) ('0' + j); + } + lookUpBase64Alphabet[62] = (char) '+'; + lookUpBase64Alphabet[63] = (char) '/'; + + } + + private static boolean isWhiteSpace(char octect) { + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); + } + + private static boolean isPad(char octect) { + return (octect == PAD); + } + + private static boolean isData(char octect) { + return (octect < BASELENGTH && base64Alphabet[octect] != -1); + } + + /** + * file->base64 + * @param file + * @return + */ + public static String encode(File file){ + String result = ""; + if (file != null && file.exists() && file.isFile()){ + FileInputStream inputStream = null; + byte[] buffer = null; + try { + inputStream = new FileInputStream(file); + buffer = new byte[(int) file.length()]; + inputStream.read(buffer); + inputStream.close(); + }catch (Exception e){ + e.printStackTrace(); + }finally { + closeIO(inputStream); + } + if (buffer != null){ + result = encode(buffer); + } + } + return result; + } + + /** + * Encodes hex octects into Base64 + * + * @param binaryData + * Array containing binaryData + * @return Encoded Base64 array + */ + public static String encode(byte[] binaryData) { + + if (binaryData == null) { + return null; + } + + int lengthDataBits = binaryData.length * EIGHTBIT; + if (lengthDataBits == 0) { + return ""; + } + + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 + : numberTriplets; + char encodedData[] = null; + + encodedData = new char[numberQuartet * 4]; + + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; + + int encodedIndex = 0; + int dataIndex = 0; + + for (int i = 0; i < numberTriplets; i++) { + b1 = binaryData[dataIndex++]; + b2 = binaryData[dataIndex++]; + b3 = binaryData[dataIndex++]; + + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) + : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) + : (byte) ((b2) >> 4 ^ 0xf0); + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) + : (byte) ((b3) >> 6 ^ 0xfc); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; + } + + // form integral number of 6-bit groups + if (fewerThan24bits == EIGHTBIT) { + b1 = binaryData[dataIndex]; + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) + : (byte) ((b1) >> 2 ^ 0xc0); + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; + encodedData[encodedIndex++] = PAD; + encodedData[encodedIndex++] = PAD; + } else if (fewerThan24bits == SIXTEENBIT) { + b1 = binaryData[dataIndex]; + b2 = binaryData[dataIndex + 1]; + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) + : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) + : (byte) ((b2) >> 4 ^ 0xf0); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; + encodedData[encodedIndex++] = PAD; + } + + return new String(encodedData); + } + + /** + * Decodes Base64 data into octects + * + * @param encoded + * string containing Base64 data + * @return Array containind decoded data. + */ + public static byte[] decode(String encoded) { + + if (encoded == null) { + return null; + } + + char[] base64Data = encoded.toCharArray(); + // remove white spaces + int len = removeWhiteSpace(base64Data); + + if (len % FOURBYTE != 0) { + return null;// should be divisible by four + } + + int numberQuadruple = (len / FOURBYTE); + + if (numberQuadruple == 0) { + return new byte[0]; + } + + byte decodedData[] = null; + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; + char d1 = 0, d2 = 0, d3 = 0, d4 = 0; + + int i = 0; + int encodedIndex = 0; + int dataIndex = 0; + decodedData = new byte[(numberQuadruple) * 3]; + + for (; i < numberQuadruple - 1; i++) { + + if (!isData((d1 = base64Data[dataIndex++])) + || !isData((d2 = base64Data[dataIndex++])) + || !isData((d3 = base64Data[dataIndex++])) + || !isData((d4 = base64Data[dataIndex++]))) { + return null; + }// if found "no data" just return null + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + } + + if (!isData((d1 = base64Data[dataIndex++])) + || !isData((d2 = base64Data[dataIndex++]))) { + return null;// if found "no data" just return null + } + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + + d3 = base64Data[dataIndex++]; + d4 = base64Data[dataIndex++]; + if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters + if (isPad(d3) && isPad(d4)) { + if ((b2 & 0xf) != 0)// last 4 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 1]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + return tmp; + } else if (!isPad(d3) && isPad(d4)) { + b3 = base64Alphabet[d3]; + if ((b3 & 0x3) != 0)// last 2 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 2]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + return tmp; + } else { + return null; + } + } else { // No PAD e.g 3cQl + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + + } + + return decodedData; + } + + /** + * remove WhiteSpace from MIME containing encoded Base64 data. + * + * @param data + * the byte array of base64 data (with WS) + * @return the new length + */ + private static int removeWhiteSpace(char[] data) { + if (data == null) { + return 0; + } + + // count characters that's not whitespace + int newSize = 0; + int len = data.length; + for (int i = 0; i < len; i++) { + if (!isWhiteSpace(data[i])) { + data[newSize++] = data[i]; + } + } + return newSize; + } + + public static void closeIO(Closeable... closeables) { + if (null != closeables && closeables.length > 0) { + for (Closeable closeable : closeables) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (Exception e) { + throw new RuntimeException("", e); + } + } + } + } +} + diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/MainActivity.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/MainActivity.java index c1d05a6..562ea95 100755 --- a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/MainActivity.java +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/MainActivity.java @@ -1,6 +1,5 @@ package sdk.im.qunar.com.qtalksdkdemo; -import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; @@ -10,13 +9,17 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; + import com.qunar.im.common.CommonConfig; import com.qunar.im.ui.activity.TabMainActivity; import com.qunar.im.ui.sdk.QIMSdk; +import sdk.im.qunar.com.qtalksdkdemo.permission.OnPermissionListener; +import sdk.im.qunar.com.qtalksdkdemo.permission.PermissionX; -public class MainActivity extends Activity { +public class MainActivity extends AppCompatActivity { private Button autoLoginButton,startPlatForm; private TextView logcat_text; @@ -49,7 +52,7 @@ public void initQIMSdk(View view) { * @param view */ public void configNavigation(View view) { - String url = "";//导航URl + String url = UserInfo.NAV;//导航URl if(TextUtils.isEmpty(url)){ toast("请配置正确的导航地址"); return; @@ -75,8 +78,8 @@ public void login(View view) { toast(s); }); }else { - final String uid = "";//用户名 - final String password = "";//密码 + final String uid = UserInfo.UID;//用户名 + final String password = UserInfo.PASSWORD;//密码 QIMSdk.getInstance().login(uid, password, (b, s) -> { logcat_text.append("Uid:" + uid + "\n" + "Password:" + password); pd.dismiss(); @@ -95,7 +98,25 @@ public void login(View view) { * @param view */ public void goToChat(View view){ - QIMSdk.getInstance().goToChatConv(this,"jid",0); + PermissionX.with(this) + .storage() + .setPermissionListener(new OnPermissionListener() { + @Override + public void onDenied() { + + } + + @Override + public void onGranted() { + QIMSdk.getInstance().goToChatConv(MainActivity.this,"jid",0); + } + + @Override + public void onCancel() { + + } + }) + .start(); } /** diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/UserInfo.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/UserInfo.java new file mode 100644 index 0000000..460e792 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/UserInfo.java @@ -0,0 +1,7 @@ +package sdk.im.qunar.com.qtalksdkdemo; + +public class UserInfo { + public static final String UID = "test02"; + public static final String PASSWORD = "12345678"; + public static final String NAV = "https://dev.fsll.tech:8443/startalk_nav"; +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/AbsPermissionTask.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/AbsPermissionTask.java new file mode 100644 index 0000000..3b2379d --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/AbsPermissionTask.java @@ -0,0 +1,29 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +public abstract class AbsPermissionTask implements PermissionTask{ + + private boolean request_permission_always = false;//总是请求权限,如果被拒绝就弹窗提示 + + @Override + public boolean deniedPermission(Context context, PermissionFragment fragment) { + return false; + } + + @Override + public boolean mustHave() { + return false; + } + + @Override + public boolean isRequestAlways() { + return request_permission_always; + } + + @Override + public PermissionTask setRequestAlways() { + request_permission_always = true; + return this; + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/DialogAlert.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/DialogAlert.java new file mode 100644 index 0000000..8597ef4 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/DialogAlert.java @@ -0,0 +1,110 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; +import android.content.DialogInterface; +import android.text.TextUtils; + +import androidx.appcompat.app.AlertDialog; + +import sdk.im.qunar.com.qtalksdkdemo.R; + + +/** + * 说明:DialogAlert + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-18 13:41 + *

+ * 版本:verson 1.0 + */ +public class DialogAlert { + + public final Context mContext; + + private DialogAlert(Context context) { + this.mContext = context; + } + + public static DialogAlert create(Context context){ + return new DialogAlert(context); + } + + public DialogInterface.OnClickListener confirmListener; + public DialogInterface.OnClickListener cancelListener; + public String confirmText; + public String cancelText; + public String title; + public String message; + public boolean cancel = true; + + public DialogAlert setCancel(boolean cancel) { + this.cancel = cancel; + return this; + } + + public DialogAlert setConfirmText(String confirmText) { + this.confirmText = confirmText; + return this; + } + + public DialogAlert setCancelText(String cancelText) { + this.cancelText = cancelText; + return this; + } + + public DialogAlert setConfirmListener(DialogInterface.OnClickListener confirmListener) { + this.confirmListener = confirmListener; + return this; + } + + public DialogAlert setCancelListener(DialogInterface.OnClickListener cancelListener) { + this.cancelListener = cancelListener; + return this; + } + + public DialogAlert setTitle(String title) { + this.title = title; + return this; + } + + public DialogAlert setMessage(String message) { + this.message = message; + return this; + } + + private String getTitle(){ + if (TextUtils.isEmpty(title)){ + return "提示"; + }else { + return title; + } + } + + public String getMessage() { + if (TextUtils.isEmpty(message)){ + return ""; + }else { + return message; + } + } + + public void show(){ + if (mContext != null) { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(mContext); + alertBuilder.setTitle(getTitle()); + alertBuilder.setMessage(getMessage()); + if (!TextUtils.isEmpty(confirmText)) { + alertBuilder.setPositiveButton(confirmText, confirmListener); + } + if (!TextUtils.isEmpty(cancelText)) { + alertBuilder.setNegativeButton(cancelText, cancelListener); + } + alertBuilder.setCancelable(cancel); + alertBuilder.create().show(); + } + } + +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/IPermissionDialogDeploy.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/IPermissionDialogDeploy.java new file mode 100644 index 0000000..489311b --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/IPermissionDialogDeploy.java @@ -0,0 +1,22 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + + +public class IPermissionDialogDeploy { + public static String CANCEL = "暂不"; + public static String TO_SETTING = "去设置"; + public static String MSG_READ_PHONE_STATE = String.format("您未允许%s获取手机状态权限,您可在系统设置中开启", appName()); + public static String MSG_STORAGE = String.format("您未允许%s获取存储权限,您可在系统设置中开启", appName()); + public static String MSG_CAMERA = String.format("您未允许%s获取摄像头权限,您可在系统设置中开启", appName()); + public static String MSG_AUDIO = String.format("您未允许%s获取录音权限,您可在系统设置中开启", appName()); + public static String MSG_CONTACTS = String.format("您未允许%s获取通讯录权限,您可在系统设置中开启", appName()); + public static String MSG_LOCATION = String.format("您未允许%s获取定位权限,您可在系统设置中开启", appName()); + + + /** + * 说明:获取应用名称 + * @return + */ + public static String appName(){ + return ""; + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/OnPermissionListener.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/OnPermissionListener.java new file mode 100644 index 0000000..0ba0ff6 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/OnPermissionListener.java @@ -0,0 +1,31 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + + +/** + * 说明:OnPermissionListener + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019/4/23 17:12 + *

+ * 版本:verson 1.0 + */ +public interface OnPermissionListener { + + /** + * 当用户拒绝某一项权限后回调 + */ + void onDenied(); + + /** + * 用户允许所有权限后回调 + */ + void onGranted(); + + /** + * 用户取消权限后回调 + */ + void onCancel(); +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionAudio.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionAudio.java new file mode 100644 index 0000000..3d00c2a --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionAudio.java @@ -0,0 +1,33 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +import com.yanzhenjie.permission.runtime.Permission; + +/** + * 说明:PermissionAudio + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:43 + *

+ * 版本:verson 1.0 + */ +public class PermissionAudio extends AbsPermissionTask{ + + @Override + public String[] permissionGroup() { + return new String[]{Permission.RECORD_AUDIO}; + } + + @Override + public String deniedMessage() { + return IPermissionDialogDeploy.MSG_AUDIO; + } + + public static boolean havePermission(Context context){ + return PermissionX.hasPermissions(context, Permission.RECORD_AUDIO); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionCamera.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionCamera.java new file mode 100644 index 0000000..df0b03f --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionCamera.java @@ -0,0 +1,33 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +import com.yanzhenjie.permission.runtime.Permission; + +/** + * 说明:PermissionCamera + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:43 + *

+ * 版本:verson 1.0 + */ +public class PermissionCamera extends AbsPermissionTask{ + + @Override + public String[] permissionGroup() { + return new String[]{Permission.CAMERA}; + } + + @Override + public String deniedMessage() { + return IPermissionDialogDeploy.MSG_CAMERA; + } + + public static boolean havePermission(Context context){ + return PermissionX.hasPermissions(context, Permission.CAMERA); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionContacts.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionContacts.java new file mode 100644 index 0000000..c27f440 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionContacts.java @@ -0,0 +1,33 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +import com.yanzhenjie.permission.runtime.Permission; + +/** + * 说明:PermissionContacts + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:43 + *

+ * 版本:verson 1.0 + */ +public class PermissionContacts extends AbsPermissionTask{ + + @Override + public String[] permissionGroup() { + return new String[]{Permission.READ_CONTACTS}; + } + + @Override + public String deniedMessage() { + return IPermissionDialogDeploy.MSG_CONTACTS; + } + + public static boolean havePermission(Context context){ + return PermissionX.hasPermissions(context, Permission.READ_CONTACTS); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionFragment.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionFragment.java new file mode 100644 index 0000000..8dff302 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionFragment.java @@ -0,0 +1,147 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Build; + +import androidx.fragment.app.Fragment; + +import com.yanzhenjie.permission.Action; +import com.yanzhenjie.permission.AndPermission; +import com.yanzhenjie.permission.Rationale; +import com.yanzhenjie.permission.RequestExecutor; + +import java.util.List; + +/** + * 说明:SoonPermissionFragment + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019/6/3 18:16 + *

+ * 版本:verson 1.0 + */ +public class PermissionFragment extends Fragment { + + private PermissionX mSoonPermission; + private PermissionOptional mPermissionOptional = new PermissionOptional(); + + private Rationale> mRationale = new Rationale>() { + @Override + public void showRationale(Context context, List data, RequestExecutor executor) { + executor.execute(); + } + }; + + private Action> deniedAction = new Action>() { + @Override + public void onAction(List data) { + if (mPermissionOptional != null){ + mPermissionOptional.onOptionalDenied(getActivity(), PermissionFragment.this); + } + } + }; + private Action> grantedAction = new Action>() { + @Override + public void onAction(List data) { + if (mSoonPermission != null){ + mSoonPermission.start(); + } + } + }; + + public PermissionFragment(){} + + public void setTargetListener(OnPermissionListener listener){ + if (mPermissionOptional != null){ + mPermissionOptional.setTarget(listener); + } + } + + public PermissionOptional getPermissionOptional() { + return mPermissionOptional; + } + + public void setSoonPermission(PermissionX soonPermission){ + mSoonPermission = soonPermission; + } + + public void requestPermission(){ + if (mSoonPermission != null){ + if (PermissionX.hasPermissions(getActivity(), mSoonPermission.getCurrentTask().permissionGroup())){ + mSoonPermission.start(); + }else { + AndPermission.with(this) + .runtime() + .permission(mSoonPermission.getCurrentTask().permissionGroup()) + .rationale(mRationale) + .onDenied(deniedAction) + .onGranted(grantedAction) + .start(); + } + } + } + + public PermissionX getSoonPermission(){ + return mSoonPermission; + } + + public boolean hasAlwaysDenied(Context context) { + return AndPermission.hasAlwaysDeniedPermission(context, mSoonPermission.getCurrentTask().permissionGroup()); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PermissionX.REQUEST_CODE){ + PermissionTask task = mSoonPermission.getCurrentTask(); + if (task != null){ + if (PermissionX.hasPermissions(getContext(), task.permissionGroup())){ + mSoonPermission.restartCurrentTask(); + }else { + if (!isMeizu()){ + if (mPermissionOptional != null){ + mPermissionOptional.onOptionalDenied(getActivity(), PermissionFragment.this); + } + } + } + } + } + } + + private boolean isMeizu(){ + return Build.MANUFACTURER.toLowerCase().contains("meizu"); + } + + public void showDeniedDialog(){ + DialogAlert.create(getContext()) + .setCancel(false) + .setMessage(mSoonPermission.getCurrentTask().deniedMessage()) + .setCancelText(IPermissionDialogDeploy.CANCEL) + .setCancelListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + if (mPermissionOptional != null){ + mPermissionOptional.onCancel(); + } + } + }) + .setConfirmText(IPermissionDialogDeploy.TO_SETTING) + .setConfirmListener(new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + AndPermission.with(PermissionFragment.this) + .runtime() + .setting() + .start(PermissionX.REQUEST_CODE); + } + }) + .show(); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionLocation.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionLocation.java new file mode 100644 index 0000000..be86031 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionLocation.java @@ -0,0 +1,33 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +import com.yanzhenjie.permission.runtime.Permission; + +/** + * 说明:PermissionLocation + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:43 + *

+ * 版本:verson 1.0 + */ +public class PermissionLocation extends AbsPermissionTask{ + + @Override + public String[] permissionGroup() { + return new String[]{Permission.ACCESS_COARSE_LOCATION,Permission.ACCESS_FINE_LOCATION}; + } + + @Override + public String deniedMessage() { + return IPermissionDialogDeploy.MSG_LOCATION; + } + + public static boolean havePermission(Context context){ + return PermissionX.hasPermissions(context, Permission.ACCESS_COARSE_LOCATION, Permission.ACCESS_FINE_LOCATION); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionOptional.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionOptional.java new file mode 100644 index 0000000..db4ed07 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionOptional.java @@ -0,0 +1,78 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +/** + * 说明:PermissionOptional + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019/6/4 10:53 + *

+ * 版本:verson 1.0 + */ +public class PermissionOptional { + + private OnPermissionListener mTarget; + + public PermissionOptional(){} + + public void setTarget(OnPermissionListener listener){ + this.mTarget = listener; + } + + public boolean onOptionalDenied(final Context context,final PermissionFragment fragment) { + if (fragment != null){ + PermissionTask task = fragment.getSoonPermission().getCurrentTask(); + if (task != null){ + if (!task.deniedPermission(context,fragment)){ + if (fragment.getSoonPermission().isSequenceStrategy()){ + if (fragment.hasAlwaysDenied(context)){ + fragment.showDeniedDialog(); + }else { + fragment.getSoonPermission().start(); + } + }else if (fragment.getSoonPermission().isInterceptStrategy()){ + if (task.isRequestAlways() || task.mustHave()){ + if (fragment.hasAlwaysDenied(context)){ + fragment.showDeniedDialog(); + }else { + fragment.requestPermission(); + } + }else { + if (fragment.hasAlwaysDenied(context)){ + fragment.showDeniedDialog(); + }else { + fragment.getPermissionOptional().onDenied(); + } + } + } + } + } + return true; + }else { + return false; + } + } + + public void onDenied(){ + if (mTarget != null){ + mTarget.onDenied(); + } + } + + public void onGranted() { + if (mTarget != null){ + mTarget.onGranted(); + } + } + + public void onCancel() { + if (mTarget != null){ + mTarget.onCancel(); + } + } + +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionReadPhoneState.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionReadPhoneState.java new file mode 100644 index 0000000..0aa2c08 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionReadPhoneState.java @@ -0,0 +1,48 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +import com.yanzhenjie.permission.runtime.Permission; + +/** + * 说明:PermissionReadPhoneState(Android10废弃这个权限) + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:43 + *

+ * 版本:verson 1.0 + */ +@Deprecated +public class PermissionReadPhoneState extends AbsPermissionTask{ + + public PermissionReadPhoneState(){ + setRequestAlways(); + } + + @Override + public String[] permissionGroup() { + return new String[]{Permission.READ_PHONE_STATE}; + } + + @Override + public String deniedMessage() { + return IPermissionDialogDeploy.MSG_READ_PHONE_STATE; + } + + @Override + public boolean mustHave() { + return true; + } + + /** + * 是否有获取设备状态权限 + * @param context + * @return + */ + public static boolean havePermission(Context context){ + return PermissionX.hasPermissions(context, Permission.READ_PHONE_STATE); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionStorage.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionStorage.java new file mode 100644 index 0000000..91b69fc --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionStorage.java @@ -0,0 +1,34 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +import com.yanzhenjie.permission.runtime.Permission; + +/** + * 说明:PermissionStorage + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:43 + *

+ * 版本:verson 1.0 + */ +@Deprecated +public class PermissionStorage extends AbsPermissionTask{ + + @Override + public String[] permissionGroup() { + return new String[]{Permission.WRITE_EXTERNAL_STORAGE,Permission.READ_EXTERNAL_STORAGE}; + } + + @Override + public String deniedMessage() { + return IPermissionDialogDeploy.MSG_STORAGE; + } + + public static boolean havePermission(Context context){ + return PermissionX.hasPermissions(context, Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE); + } +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionTask.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionTask.java new file mode 100644 index 0000000..dac8129 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionTask.java @@ -0,0 +1,47 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; + +/** + * 说明:PermissionTask + *

+ * 作者:fanly + *

+ * 类型:Class + *

+ * 时间:2019-06-19 13:39 + *

+ * 版本:verson 1.0 + */ +public interface PermissionTask { + + /** + * 拒绝权限 + * @param context + * @param fragment + * @return + */ + boolean deniedPermission(final Context context, final PermissionFragment fragment); + + /** + * 权限组 + * @return + */ + String[] permissionGroup(); + + /** + * 是否必须获取权限 + * @return + */ + @Deprecated + boolean mustHave(); + + /** + * 拒绝提示内容 + * @return + */ + String deniedMessage(); + + boolean isRequestAlways(); + PermissionTask setRequestAlways(); +} diff --git a/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionX.java b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionX.java new file mode 100644 index 0000000..65b89d2 --- /dev/null +++ b/app/src/main/java/sdk/im/qunar/com/qtalksdkdemo/permission/PermissionX.java @@ -0,0 +1,270 @@ +package sdk.im.qunar.com.qtalksdkdemo.permission; + +import android.content.Context; +import android.os.Build; + +import androidx.annotation.IntDef; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import com.yanzhenjie.permission.AndPermission; +import com.yanzhenjie.permission.runtime.Permission; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + + +public class PermissionX { + + private final String TAG_SOON_PERMISSION_FRAGMENT = "TAG_SOON_PERMISSION_FRAGMENT"; + public final static int REQUEST_CODE = 9001; + + private boolean hasDeniedPermission = false; + private PermissionFragment mSoonPermissionFragment; + private PermissionTask mCurrentTask; + private Queue mPermissionTaskQueue; + + + @IntDef({SEQUENCE, INTERCEPT}) + @Retention(RetentionPolicy.SOURCE) + public @interface CheckStrategy {} + + public static final int SEQUENCE = 1;//按照顺序检查权限 + public static final int INTERCEPT = 2;//按照顺序检查权限,拦截模式 + private int checkStrategy = INTERCEPT; + + private PermissionX(FragmentActivity activity, FragmentManager manager) { + findSoonPermissionFragment(activity, manager); + /** + * 默认拦截模式 + */ + checkStrategy(INTERCEPT); + } + + public static PermissionX with(FragmentActivity activity) { + return new PermissionX(activity, activity.getSupportFragmentManager()); + } + + public static PermissionX with(Fragment fragment) { + if (fragment == null) { + return new PermissionX(null, null); + } else { + return new PermissionX(fragment.getActivity(), fragment.getChildFragmentManager()); + } + } + + private void findSoonPermissionFragment(FragmentActivity activity, FragmentManager manager) { + if (activity != null && manager != null) { + Fragment fragment = manager.findFragmentByTag(TAG_SOON_PERMISSION_FRAGMENT); + if (fragment == null) { + mSoonPermissionFragment = new PermissionFragment(); + manager.beginTransaction().add(mSoonPermissionFragment, TAG_SOON_PERMISSION_FRAGMENT).commitAllowingStateLoss(); + manager.executePendingTransactions(); + } else if (fragment instanceof PermissionFragment) { + mSoonPermissionFragment = (PermissionFragment) fragment; + } + } + } + + // targetSDK = 29, 默认开启Scoped Storage, 但可通过在manifest里添加requestLegacyExternalStorage = true关闭; + // targetSDK < 29, 默认不开启Scoped Storage, 但可通过在manifest里添加requestLegacyExternalStorage = false打开; + public static boolean hasPermissions(Context context, String... permissions) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {//未适配存储权限 + if (permissions == null || permissions.length == 0) { + return true; + } else if (permissions.length == 1 && Permission.READ_PHONE_STATE.equals(permissions[0])) { + return true; + }else { + return AndPermission.hasPermissions(context, permissions); + } + } else { + return AndPermission.hasPermissions(context, permissions); + } +// if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {//适配存储权限 +// if (permissions == null || permissions.length == 0) { +// return true; +// } else if (permissions.length == 1 && Permission.READ_PHONE_STATE.equals(permissions[0])) { +// return true; +// } else if (permissions.length ==2 && Permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0]) && Permission.READ_EXTERNAL_STORAGE.equals(permissions[1])){ +// return true; +// }else { +// return AndPermission.hasPermissions(context, permissions); +// } +// } else { +// return AndPermission.hasPermissions(context, permissions); +// } + } + + private void initPermissionGroupList() { + if (mPermissionTaskQueue == null) { + mPermissionTaskQueue = new ConcurrentLinkedQueue<>(); + } + } + + /** + * 设置检查模式 + * @return + */ + public PermissionX checkStrategy(@CheckStrategy int strategy){ + switch (strategy){ + case SEQUENCE: + case INTERCEPT: + checkStrategy = strategy; + break; + } + return this; + } + + public boolean isSequenceStrategy(){ + return checkStrategy == SEQUENCE; + } + + public boolean isInterceptStrategy(){ + return checkStrategy == INTERCEPT; + } + + public PermissionTask getCurrentTask() { + return mCurrentTask; + } + + public PermissionX setPermissionListener(OnPermissionListener listener) { + if (mSoonPermissionFragment != null) { + mSoonPermissionFragment.setTargetListener(listener); + } + return this; + } + + + public void restartCurrentTask() { + if (mCurrentTask != null && mPermissionTaskQueue != null) { + mPermissionTaskQueue.add(mCurrentTask); + start(); + } + } + + /** + * 开启检查权限 + */ + public void start() { + if (mSoonPermissionFragment != null) { + if (mPermissionTaskQueue != null) { + if (mCurrentTask != null && !hasDeniedPermission) { + if (!PermissionX.hasPermissions(mSoonPermissionFragment.getContext(), mCurrentTask.permissionGroup())) { + hasDeniedPermission = true; + } + } + mCurrentTask = mPermissionTaskQueue.poll(); + if (mCurrentTask != null) { + mSoonPermissionFragment.setSoonPermission(this); + mSoonPermissionFragment.requestPermission(); + } else { + if (hasDeniedPermission) { + mSoonPermissionFragment.getPermissionOptional().onDenied(); + } else { + mSoonPermissionFragment.getPermissionOptional().onGranted(); + } + removeSoonPermissionFragment(); + } + } else { + removeSoonPermissionFragment(); + } + } + } + + private void removeSoonPermissionFragment() { + if (mSoonPermissionFragment != null) { + mSoonPermissionFragment.getFragmentManager().beginTransaction().remove(mSoonPermissionFragment).commitAllowingStateLoss(); + } + } + + /*********************************************************************/ + + private PermissionX addPermissionTask(PermissionTask task) { + initPermissionGroupList(); + boolean have = false; + for (PermissionTask permissionTask : mPermissionTaskQueue) { + if (task.getClass().getSimpleName().equals(permissionTask.getClass().getSimpleName())) { + have = true; + break; + } + } + if (!have) { + mPermissionTaskQueue.add(task); + } + return this; + } + + public PermissionX addPermissionTask(Class clazz) { + try { + PermissionTask task = clazz.newInstance(); + if (task != null) { + addPermissionTask(task); + } + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + /** + * 设备状态权限(Android10无法获取到该权限) + * + * @return + */ + @Deprecated + public PermissionX readPhoneState() { + return addPermissionTask(PermissionReadPhoneState.class); + } + + /** + * 定位权限 + * + * @return + */ + public PermissionX location() { + return addPermissionTask(new PermissionLocation()); + } + + /** + * 存储权限 + * + * @return + */ + @Deprecated + public PermissionX storage() { + return addPermissionTask(new PermissionStorage()); + } + + /** + * 相机权限 + * + * @return + */ + public PermissionX camera() { + return addPermissionTask(new PermissionCamera()); + } + + /** + * 联系人权限 + * + * @return + */ + public PermissionX contacts() { + return addPermissionTask(new PermissionContacts()); + } + + + /** + * 录音权限 + * + * @return + */ + public PermissionX audio() { + return addPermissionTask(new PermissionAudio()); + } + + /*********************************************************************/ +} diff --git a/build.gradle b/build.gradle index 95c6f8f..e480f48 100644 --- a/build.gradle +++ b/build.gradle @@ -16,10 +16,10 @@ buildscript { allprojects { repositories { + maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} maven { url "https://jitpack.io" } - maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} maven { url "https://maven.google.com" } maven { url 'https://dl.google.com/dl/android/maven2' } maven { diff --git a/imsdk/build.gradle b/imsdk/build.gradle index ac16245..7f85a9e 100644 --- a/imsdk/build.gradle +++ b/imsdk/build.gradle @@ -55,6 +55,8 @@ dependencies { api 'net.zetetic:android-database-sqlcipher:3.5.4' api 'com.github.bumptech.glide:glide:3.8.0' + api 'top.zibin:Luban:1.1.8' + api 'org.jsoup:jsoup:1.9.2' //日期选择器 api 'com.contrarywind:Android-PickerView:4.1.6' diff --git a/imsdk/src/main/java/com/qunar/im/ui/activity/PbChatActivity.java b/imsdk/src/main/java/com/qunar/im/ui/activity/PbChatActivity.java index 53fa6dc..a7bd367 100644 --- a/imsdk/src/main/java/com/qunar/im/ui/activity/PbChatActivity.java +++ b/imsdk/src/main/java/com/qunar/im/ui/activity/PbChatActivity.java @@ -92,6 +92,8 @@ import com.qunar.im.base.view.faceGridView.EmoticonEntity; import com.qunar.im.common.CommonConfig; import com.qunar.im.common.CurrentPreference; +import com.qunar.im.core.imgtool.Luban; +import com.qunar.im.core.imgtool.OnCompressListener; import com.qunar.im.core.manager.IMLogicManager; import com.qunar.im.core.manager.IMPayManager; import com.qunar.im.core.services.QtalkNavicationService; @@ -461,7 +463,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.atom_ui_activity_chat); connectionUtil = ConnectionUtil.getInstance(); waterMarkTextUtil = new WaterMarkTextUtil(); -// EventBus.getDefault().register(this); + EventBus.getDefault().register(this); //bugly tag // CrashReportUtils.getInstance().setUserTag(55092); //处理一些额外的数据 @@ -824,8 +826,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { */ public void onEventMainThread(EventBusEvent.NewPictureEdit edit) { if (!TextUtils.isEmpty(edit.mPicturePath)) { - imageUrl = edit.mPicturePath; - chatingPresenter.sendImage(); + compressImageUrl(edit.mPicturePath,true); } } @@ -2695,9 +2696,7 @@ public void replaceItem(IMMessage imMessage) { @Override public void sendEditPic(String path) { - imageUrl = path; -// imageUrl = edit.mPicturePath; - chatingPresenter.sendImage(); + compressImageUrl(path,true); } @@ -2970,7 +2969,7 @@ public void getCameraImageResult(Intent data) { } else { imageUrl = data.getStringExtra("path"); if (!TextUtils.isEmpty(imageUrl)) { - chatingPresenter.sendImage(); + compressImageUrl(imageUrl,true); } } @@ -2995,8 +2994,7 @@ public void selectPhotoResult(Intent data) { ArrayList images = (ArrayList) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS); if (images.size() > 0) { for (ImageItem image : images) { - imageUrl = image.path; - chatingPresenter.sendImage(); + compressImageUrl(image.path,true); } } } @@ -3303,6 +3301,36 @@ void sendVideo() { } } + + void compressImageUrl(String path,Boolean enableCompress){ + if (!enableCompress){ + imageUrl = path; + chatingPresenter.sendImage(); + return; + } + Luban.with(getContext()) + .load(path) + .setCompressListener(new OnCompressListener() { + @Override + public void onStart() { + + } + + @Override + public void onSuccess(File file) { + imageUrl = file.getAbsolutePath(); + chatingPresenter.sendImage(); + } + + @Override + public void onError(Throwable e) { + imageUrl = path; + chatingPresenter.sendImage(); + } + }) + .launch(); + } + void selectPic() { // Intent intent1 = new Intent(this, PictureSelectorActivity.class); // intent1.putExtra("isMultiSel", true); @@ -3320,8 +3348,7 @@ public void onResult(ArrayList photos, ArrayList paths, boolean i if (paths.size() > 0) { for (Photo image : photos) { if (image.type.startsWith("image")) { - imageUrl = image.path; - chatingPresenter.sendImage(); + compressImageUrl(image.path,!isOriginal); } else if (image.type.startsWith("video")) { @@ -3440,8 +3467,7 @@ public void onGlobalLayout() { photoPop = RecommendPhotoPop.recommendPhoto(PbChatActivity.this, total_bottom_layout, latestImage.path, new View.OnClickListener() { @Override public void onClick(View v) { - imageUrl = latestImage.path; - chatingPresenter.sendImage(); + compressImageUrl(imageUrl,true); if (photoPop.isShowing()) photoPop.dismiss(); } @@ -3648,7 +3674,7 @@ public void onEmoticonClick(EmoticonEntity entity, String pkgId) { imageUrl = entity.fileOrg; } if (imageUrl != null) { - chatingPresenter.sendImage(); + compressImageUrl(imageUrl,true); } } } diff --git a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/EasyPhotos.java b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/EasyPhotos.java index 734a943..5469152 100755 --- a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/EasyPhotos.java +++ b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/EasyPhotos.java @@ -60,11 +60,11 @@ public static AlbumBuilder createCamera(Fragment fragmentV) { * @return */ public static AlbumBuilder createAlbum(FragmentActivity activity, boolean isShowCamera, @NonNull ImageEngine imageEngine) { - return AlbumBuilder.createAlbum(activity, isShowCamera, imageEngine); + return AlbumBuilder.createAlbum(activity, isShowCamera, imageEngine).setOriginalMenu(false,true,""); } public static AlbumBuilder createAlbum(Fragment fragmentV, boolean isShowCamera, @NonNull ImageEngine imageEngine) { - return AlbumBuilder.createAlbum(fragmentV, isShowCamera, imageEngine); + return AlbumBuilder.createAlbum(fragmentV, isShowCamera, imageEngine).setOriginalMenu(false,true,""); } diff --git a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/setting/Setting.java b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/setting/Setting.java index 68acfc7..c812a25 100755 --- a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/setting/Setting.java +++ b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/setting/Setting.java @@ -37,7 +37,7 @@ public class Setting { public static boolean photoAdIsOk = false; public static boolean albumItemsAdIsOk = false; public static ArrayList selectedPhotos = new ArrayList<>(); - public static boolean showOriginalMenu = false; + public static boolean showOriginalMenu = true; public static boolean originalMenuUsable = false; public static String originalMenuUnusableHint = ""; public static boolean selectedOriginal = false; diff --git a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/EasyPhotosActivity.java b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/EasyPhotosActivity.java index ebd1761..db38bdf 100755 --- a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/EasyPhotosActivity.java +++ b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/EasyPhotosActivity.java @@ -15,6 +15,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; + import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -25,14 +26,17 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; + import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; import android.view.animation.ScaleAnimation; +import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RadioButton; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -67,22 +71,23 @@ public class EasyPhotosActivity extends AppCompatActivity implements AlbumItemsAdapter.OnClickListener, PhotosAdapter.OnClickListener, AdListener, View.OnClickListener { - private AlbumModel albumModel; - private ArrayList photoList = new ArrayList<>(); + private AlbumModel albumModel; + private ArrayList photoList = new ArrayList<>(); private ArrayList albumItemList = new ArrayList<>(); private ArrayList resultList = new ArrayList<>(); - private RecyclerView rvPhotos; - private PhotosAdapter photosAdapter; + private RecyclerView rvPhotos; + private PhotosAdapter photosAdapter; private GridLayoutManager gridLayoutManager; - private RecyclerView rvAlbumItems; + private RecyclerView rvAlbumItems; private AlbumItemsAdapter albumItemsAdapter; - private RelativeLayout rootViewAlbumItems; + private RelativeLayout rootViewAlbumItems; private PressedTextView tvAlbumItems, tvDone, tvPreview; - private TextView tvOriginal; + // private TextView tvOriginal; + private RadioButton rbOriginal; private AnimatorSet setHide; private AnimatorSet setShow; @@ -93,8 +98,8 @@ public class EasyPhotosActivity extends AppCompatActivity implements AlbumItemsA private LinearLayout mSecondMenus; private RelativeLayout permissionView; - private TextView tvPermission; - private View mBottomBar; + private TextView tvPermission; + private View mBottomBar; @Override protected void onCreate(Bundle savedInstanceState) { @@ -118,7 +123,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onDestroy() { super.onDestroy(); -// Setting.clear(); + // Setting.clear(); } public static void start(Activity activity, int requestCode) { @@ -272,61 +277,61 @@ public void onClick(View view) { private void toAndroidCamera(int requestCode) { Intent intent = new Intent(this, EasyCameraActivity.class); startActivityForResult(intent, requestCode); -//系统相机功能屏蔽 -// Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); -// if (cameraIntent.resolveActivity(getPackageManager()) != null) { -// createCameraTempImageFile(); -// if (mTempImageFile != null && mTempImageFile.exists()) { -// -// Uri imageUri; -// if (Build.VERSION.SDK_INT >= 24) { -// imageUri = FileProvider.getUriForFile(this, Setting.fileProviderAuthority, -// mTempImageFile);//通过FileProvider创建一个content类型的Uri -// } else { -// imageUri = Uri.fromFile(mTempImageFile); -// } -// cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //对目标应用临时授权该Uri所代表的文件 -// -// cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI -// startActivityForResult(cameraIntent, requestCode); -// } else { -// Toast.makeText(this, R.string.camera_temp_file_error_easy_photos, Toast -// .LENGTH_SHORT).show(); -// } -// } else { -// Toast.makeText(this, R.string.msg_no_camera_easy_photos, Toast.LENGTH_SHORT).show(); -// } - } - -// private void createCameraTempImageFile() { -// File dir = new File(Environment.getExternalStorageDirectory(), File.separator + "DCIM" + -// File.separator + "Camera" + File.separator); -// if (!dir.exists() || !dir.isDirectory()) { -// if (!dir.mkdirs()) { -// dir = getExternalFilesDir(null); -// if (null == dir || !dir.exists()) { -// dir = getFilesDir(); -// if (null == dir || !dir.exists()) { -// String cacheDirPath = File.separator + "data" + File.separator + "data" + -// File.separator + getPackageName() + File.separator + "cache" + -// File.separator; -// dir = new File(cacheDirPath); -// if (!dir.exists()) { -// dir.mkdirs(); -// } -// } -// } -// } -// } -// -// try { -// mTempImageFile = File.createTempFile("IMG", ".jpg", dir); -// } catch (IOException e) { -// e.printStackTrace(); -// mTempImageFile = null; -// } -// -// } + //系统相机功能屏蔽 + // Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + // if (cameraIntent.resolveActivity(getPackageManager()) != null) { + // createCameraTempImageFile(); + // if (mTempImageFile != null && mTempImageFile.exists()) { + // + // Uri imageUri; + // if (Build.VERSION.SDK_INT >= 24) { + // imageUri = FileProvider.getUriForFile(this, Setting.fileProviderAuthority, + // mTempImageFile);//通过FileProvider创建一个content类型的Uri + // } else { + // imageUri = Uri.fromFile(mTempImageFile); + // } + // cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //对目标应用临时授权该Uri所代表的文件 + // + // cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI + // startActivityForResult(cameraIntent, requestCode); + // } else { + // Toast.makeText(this, R.string.camera_temp_file_error_easy_photos, Toast + // .LENGTH_SHORT).show(); + // } + // } else { + // Toast.makeText(this, R.string.msg_no_camera_easy_photos, Toast.LENGTH_SHORT).show(); + // } + } + + // private void createCameraTempImageFile() { + // File dir = new File(Environment.getExternalStorageDirectory(), File.separator + "DCIM" + + // File.separator + "Camera" + File.separator); + // if (!dir.exists() || !dir.isDirectory()) { + // if (!dir.mkdirs()) { + // dir = getExternalFilesDir(null); + // if (null == dir || !dir.exists()) { + // dir = getFilesDir(); + // if (null == dir || !dir.exists()) { + // String cacheDirPath = File.separator + "data" + File.separator + "data" + + // File.separator + getPackageName() + File.separator + "cache" + + // File.separator; + // dir = new File(cacheDirPath); + // if (!dir.exists()) { + // dir.mkdirs(); + // } + // } + // } + // } + // } + // + // try { + // mTempImageFile = File.createTempFile("IMG", ".jpg", dir); + // } catch (IOException e) { + // e.printStackTrace(); + // mTempImageFile = null; + // } + // + // } @Override @@ -350,11 +355,13 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } } File tempFile = null; - if (path != null) tempFile = new File(path); + if (path != null) + tempFile = new File(path); switch (resultCode) { case RESULT_OK: - if (data == null) return; + if (data == null) + return; if (Code.REQUEST_CAMERA == requestCode) { if (tempFile == null || !tempFile.exists()) { throw new RuntimeException("EasyPhotos拍照保存的图片不存在"); @@ -410,6 +417,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } if (Code.REQUEST_PREVIEW_ACTIVITY == requestCode) { + rbOriginal.setChecked(Setting.selectedOriginal); processOriginalMenu(); return; } @@ -475,10 +483,7 @@ private void startCrop(Activity context, String source, Intent data) { options.setHideBottomControls(Setting.isHideUCropControls); File cacheFile = new File(context.getCacheDir(), destinationFileName); - UCrop.of(Uri.fromFile(new File(source)), Uri.fromFile(cacheFile)) - .withAspectRatio(Setting.aspectRatio[0], Setting.aspectRatio[1]) - .withOptions(options) - .start(context); + UCrop.of(Uri.fromFile(new File(source)), Uri.fromFile(cacheFile)).withAspectRatio(Setting.aspectRatio[0], Setting.aspectRatio[1]).withOptions(options).start(context); } private void addNewPhoto(Photo photo) { @@ -573,25 +578,25 @@ private void onResult(File file) { Result.addPhoto(photo); done(); -// Intent data = new Intent(); - -// resultList.add(photo); -// -// data.putParcelableArrayListExtra(EasyPhotos.RESULT_PHOTOS, resultList); -// -// data.putExtra(EasyPhotos.RESULT_SELECTED_ORIGINAL, Setting.selectedOriginal); -// -// ArrayList pathList = new ArrayList<>(); -// pathList.add(photo.path); -// -// data.putStringArrayListExtra(EasyPhotos.RESULT_PATHS, pathList); -// -// if (Setting.isCrop) { -// startCrop(this, file.getAbsolutePath(), data); -// } else { -// setResult(RESULT_OK, data); -// finish(); -// } + // Intent data = new Intent(); + + // resultList.add(photo); + // + // data.putParcelableArrayListExtra(EasyPhotos.RESULT_PHOTOS, resultList); + // + // data.putExtra(EasyPhotos.RESULT_SELECTED_ORIGINAL, Setting.selectedOriginal); + // + // ArrayList pathList = new ArrayList<>(); + // pathList.add(photo.path); + // + // data.putStringArrayListExtra(EasyPhotos.RESULT_PATHS, pathList); + // + // if (Setting.isCrop) { + // startCrop(this, file.getAbsolutePath(), data); + // } else { + // setResult(RESULT_OK, data); + // finish(); + // } return; } addNewPhoto(photo); @@ -605,8 +610,10 @@ private void initView() { if (albumModel.getAlbumItems().isEmpty()) { Toast.makeText(this, R.string.no_photos_easy_photos, Toast.LENGTH_LONG).show(); - if (Setting.isShowCamera) launchCamera(Code.REQUEST_CAMERA); - else finish(); + if (Setting.isShowCamera) + launchCamera(Code.REQUEST_CAMERA); + else + finish(); return; } @@ -636,7 +643,8 @@ private void initView() { photoList.add(index, Setting.photosAdView); } if (Setting.isShowCamera && !Setting.isBottomRightCamera()) { - if (Setting.hasPhotosAd()) index = 1; + if (Setting.hasPhotosAd()) + index = 1; photoList.add(index, null); } photosAdapter = new PhotosAdapter(this, photoList, this); @@ -656,18 +664,20 @@ public int getSpanSize(int position) { } rvPhotos.setLayoutManager(gridLayoutManager); rvPhotos.setAdapter(photosAdapter); - tvOriginal = findViewById(R.id.tv_original); + // tvOriginal = findViewById(R.id.tv_original); + rbOriginal = findViewById(R.id.rb_original); if (Setting.showOriginalMenu) { processOriginalMenu(); } else { - tvOriginal.setVisibility(View.GONE); + // tvOriginal.setVisibility(View.GONE); + rbOriginal.setVisibility(View.GONE); } tvPreview = findViewById(R.id.tv_preview); initAlbumItems(); shouldShowMenuDone(); setClick(R.id.iv_album_items, R.id.tv_clear, R.id.iv_second_menu, R.id.tv_puzzle); - setClick(tvAlbumItems, rootViewAlbumItems, tvDone, tvOriginal, tvPreview, ivCamera); + setClick(tvAlbumItems, rootViewAlbumItems, tvDone, rbOriginal, tvPreview, ivCamera); } @@ -722,14 +732,13 @@ public void onClick(View v) { photosAdapter.change(); shouldShowMenuDone(); processSecondMenu(); - } else if (R.id.tv_original == id) { + } else if (R.id.rb_original == id) { if (!Setting.originalMenuUsable) { Toast.makeText(this, Setting.originalMenuUnusableHint, Toast.LENGTH_SHORT).show(); return; } Setting.selectedOriginal = !Setting.selectedOriginal; - processOriginalMenu(); - processSecondMenu(); + rbOriginal.setChecked(Setting.selectedOriginal); } else if (R.id.tv_preview == id) { PreviewActivity.start(EasyPhotosActivity.this, -1, 0); } else if (R.id.fab_camera == id) { @@ -780,14 +789,23 @@ private void done() { } private void processOriginalMenu() { - if (!Setting.showOriginalMenu) return; + if (!Setting.showOriginalMenu) { + rbOriginal.setVisibility(View.GONE); + return; + } if (Setting.selectedOriginal) { - tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_accent)); + rbOriginal.setEnabled(true); + rbOriginal.setChecked(true); + // tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_accent)); } else { if (Setting.originalMenuUsable) { - tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary)); + rbOriginal.setEnabled(true); + rbOriginal.setChecked(false); + // tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary)); } else { - tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary_dark)); + rbOriginal.setChecked(false); + rbOriginal.setEnabled(false); + // tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary_dark)); } } } @@ -811,8 +829,7 @@ private void newAnimators() { } private void newShowAnim() { - ObjectAnimator translationShow = ObjectAnimator.ofFloat(rvAlbumItems, "translationY", - mBottomBar.getTop(), 0); + ObjectAnimator translationShow = ObjectAnimator.ofFloat(rvAlbumItems, "translationY", mBottomBar.getTop(), 0); ObjectAnimator alphaShow = ObjectAnimator.ofFloat(rootViewAlbumItems, "alpha", 0.0f, 1.0f); translationShow.setDuration(300); setShow = new AnimatorSet(); @@ -821,8 +838,7 @@ private void newShowAnim() { } private void newHideAnim() { - ObjectAnimator translationHide = ObjectAnimator.ofFloat(rvAlbumItems, "translationY", 0, - mBottomBar.getTop()); + ObjectAnimator translationHide = ObjectAnimator.ofFloat(rvAlbumItems, "translationY", 0, mBottomBar.getTop()); ObjectAnimator alphaHide = ObjectAnimator.ofFloat(rootViewAlbumItems, "alpha", 1.0f, 0.0f); translationHide.setDuration(200); setHide = new AnimatorSet(); @@ -853,7 +869,8 @@ private void updatePhotos(int currAlbumItemIndex) { photoList.add(index, Setting.photosAdView); } if (Setting.isShowCamera && !Setting.isBottomRightCamera()) { - if (Setting.hasPhotosAd()) index = 1; + if (Setting.hasPhotosAd()) + index = 1; photoList.add(index, null); } photosAdapter.change(); @@ -878,17 +895,17 @@ private void shouldShowMenuDone() { tvDone.setVisibility(View.VISIBLE); tvPreview.setVisibility(View.VISIBLE); } - if(Setting.isDistinguish){ - if(Result.count()>0){ - if(Result.photos.get(0).type.contains(Type.VIDEO)){ + if (Setting.isDistinguish) { + if (Result.count() > 0) { + if (Result.photos.get(0).type.contains(Type.VIDEO)) { tvDone.setText(getString(R.string.selector_action_done_easy_photos, Result.count(), Setting.videoCount)); - }else if(Result.photos.get(0).type.contains(Type.IMAGE)){ + } else if (Result.photos.get(0).type.contains(Type.IMAGE)) { tvDone.setText(getString(R.string.selector_action_done_easy_photos, Result.count(), Setting.pictureCount)); - }else{ + } else { tvDone.setText(getString(R.string.selector_action_done_easy_photos, Result.count(), Setting.count)); } } - }else { + } else { tvDone.setText(getString(R.string.selector_action_done_easy_photos, Result.count(), Setting.count)); } } diff --git a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/PreviewActivity.java b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/PreviewActivity.java index f788de8..1423414 100755 --- a/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/PreviewActivity.java +++ b/imsdk/src/main/java/com/qunar/im/ui/util/easyphoto/easyphotos/ui/PreviewActivity.java @@ -19,8 +19,10 @@ import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; +import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.RadioButton; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -77,19 +79,20 @@ public void run() { }; private boolean mVisible; View decorView; - private TextView tvOriginal, tvNumber; - private PressedTextView tvDone; - private ImageView ivSelector; - private RecyclerView rvPhotos; + private TextView tvNumber; + private RadioButton rbOriginal; + private PressedTextView tvDone; + private ImageView ivSelector; + private RecyclerView rvPhotos; private PreviewPhotosAdapter adapter; - private PagerSnapHelper snapHelper; - private LinearLayoutManager lm; - private int index; - private ArrayList photos = new ArrayList<>(); - private int resultCode = RESULT_CANCELED; - private int lastPosition = 0;//记录recyclerView最后一次角标位置,用于判断是否转换了item - private boolean isSingle = Setting.count == 1; - private boolean unable = Result.count() == Setting.count; + private PagerSnapHelper snapHelper; + private LinearLayoutManager lm; + private int index; + private ArrayList photos = new ArrayList<>(); + private int resultCode = RESULT_CANCELED; + private int lastPosition = 0;//记录recyclerView最后一次角标位置,用于判断是否转换了item + private boolean isSingle = Setting.count == 1; + private boolean unable = Result.count() == Setting.count; private FrameLayout flFragment; private PreviewFragment previewFragment; @@ -239,16 +242,23 @@ private void initView() { ivSelector = (ImageView) findViewById(R.id.iv_selector); tvNumber = (TextView) findViewById(R.id.tv_number); tvDone = (PressedTextView) findViewById(R.id.tv_done); - tvOriginal = (TextView) findViewById(R.id.tv_original); + rbOriginal = findViewById(R.id.rb_original); flFragment = (FrameLayout) findViewById(R.id.fl_fragment); previewFragment = (PreviewFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_preview); if (Setting.showOriginalMenu) { processOriginalMenu(); + rbOriginal.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Setting.selectedOriginal = !Setting.selectedOriginal; + rbOriginal.setChecked(Setting.selectedOriginal); + } + }); } else { - tvOriginal.setVisibility(View.GONE); + rbOriginal.setVisibility(View.GONE); } - setClick(tvOriginal, tvDone, ivSelector); + setClick( tvDone, ivSelector); initRecyclerView(); shouldShowMenuDone(); @@ -302,13 +312,6 @@ public void onClick(View v) { doBack(); } else if (R.id.tv_selector == id || R.id.iv_selector == id) { updateSelector(); - } else if (R.id.tv_original == id) { - if (!Setting.originalMenuUsable) { - Toast.makeText(this, Setting.originalMenuUnusableHint, Toast.LENGTH_SHORT).show(); - return; - } - Setting.selectedOriginal = !Setting.selectedOriginal; - processOriginalMenu(); } else if (R.id.tv_done == id) { Intent intent = new Intent(); intent.putExtra(Key.PREVIEW_CLICK_DONE, true); @@ -324,12 +327,16 @@ public void onClick(View v) { private void processOriginalMenu() { if (Setting.selectedOriginal) { - tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_accent)); + rbOriginal.setChecked(true); +// tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_accent)); } else { if (Setting.originalMenuUsable) { - tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary)); + rbOriginal.setChecked(false); +// tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary)); } else { - tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary_dark)); + rbOriginal.setChecked(false); + rbOriginal.setEnabled(false); +// tvOriginal.setTextColor(ContextCompat.getColor(this, R.color.easy_photos_fg_primary_dark)); } } } diff --git a/imsdk/src/main/res/layout/activity_easy_photos.xml b/imsdk/src/main/res/layout/activity_easy_photos.xml index 53e47a2..2b0ab76 100755 --- a/imsdk/src/main/res/layout/activity_easy_photos.xml +++ b/imsdk/src/main/res/layout/activity_easy_photos.xml @@ -76,25 +76,41 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> - + + + + + + + + + + + + + + + + + android:checked="false" + android:textColor="@color/white_easy_photos" + android:text="@string/original_easy_photos"/> @@ -161,8 +179,8 @@ android:layout_height="0dp" android:padding="13dp" app:layout_constraintBottom_toBottomOf="@+id/m_bottom_bar" - app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" + app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="@+id/m_bottom_bar" app:srcCompat="@drawable/ic_camera_view_edit_easy_photos" /> diff --git a/imsdk/src/main/res/layout/activity_preview_easy_photos.xml b/imsdk/src/main/res/layout/activity_preview_easy_photos.xml index 644b4f1..9a710be 100755 --- a/imsdk/src/main/res/layout/activity_preview_easy_photos.xml +++ b/imsdk/src/main/res/layout/activity_preview_easy_photos.xml @@ -124,16 +124,16 @@ android:textStyle="bold" android:visibility="gone" /> - + android:checked="false" + android:textColor="@color/white_easy_photos" /> = 'A'; i--) { + base64Alphabet[i] = (byte) (i - 'A'); + } + for (int i = 'z'; i >= 'a'; i--) { + base64Alphabet[i] = (byte) (i - 'a' + 26); + } + + for (int i = '9'; i >= '0'; i--) { + base64Alphabet[i] = (byte) (i - '0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + + for (int i = 0; i <= 25; i++) { + lookUpBase64Alphabet[i] = (char) ('A' + i); + } + + for (int i = 26, j = 0; i <= 51; i++, j++) { + lookUpBase64Alphabet[i] = (char) ('a' + j); + } + + for (int i = 52, j = 0; i <= 61; i++, j++) { + lookUpBase64Alphabet[i] = (char) ('0' + j); + } + lookUpBase64Alphabet[62] = (char) '+'; + lookUpBase64Alphabet[63] = (char) '/'; + + } + + private static boolean isWhiteSpace(char octect) { + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); + } + + private static boolean isPad(char octect) { + return (octect == PAD); + } + + private static boolean isData(char octect) { + return (octect < BASELENGTH && base64Alphabet[octect] != -1); + } + + /** + * file->base64 + * @param file + * @return + */ + public static String encode(File file){ + String result = ""; + if (file != null && file.exists() && file.isFile()){ + FileInputStream inputStream = null; + byte[] buffer = null; + try { + inputStream = new FileInputStream(file); + buffer = new byte[(int) file.length()]; + inputStream.read(buffer); + inputStream.close(); + }catch (Exception e){ + e.printStackTrace(); + }finally { + closeIO(inputStream); + } + if (buffer != null){ + result = encode(buffer); + } + } + return result; + } + + /** + * Encodes hex octects into Base64 + * + * @param binaryData + * Array containing binaryData + * @return Encoded Base64 array + */ + public static String encode(byte[] binaryData) { + + if (binaryData == null) { + return null; + } + + int lengthDataBits = binaryData.length * EIGHTBIT; + if (lengthDataBits == 0) { + return ""; + } + + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 + : numberTriplets; + char encodedData[] = null; + + encodedData = new char[numberQuartet * 4]; + + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; + + int encodedIndex = 0; + int dataIndex = 0; + + for (int i = 0; i < numberTriplets; i++) { + b1 = binaryData[dataIndex++]; + b2 = binaryData[dataIndex++]; + b3 = binaryData[dataIndex++]; + + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) + : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) + : (byte) ((b2) >> 4 ^ 0xf0); + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) + : (byte) ((b3) >> 6 ^ 0xfc); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; + } + + // form integral number of 6-bit groups + if (fewerThan24bits == EIGHTBIT) { + b1 = binaryData[dataIndex]; + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) + : (byte) ((b1) >> 2 ^ 0xc0); + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; + encodedData[encodedIndex++] = PAD; + encodedData[encodedIndex++] = PAD; + } else if (fewerThan24bits == SIXTEENBIT) { + b1 = binaryData[dataIndex]; + b2 = binaryData[dataIndex + 1]; + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) + : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) + : (byte) ((b2) >> 4 ^ 0xf0); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; + encodedData[encodedIndex++] = PAD; + } + + return new String(encodedData); + } + + /** + * Decodes Base64 data into octects + * + * @param encoded + * string containing Base64 data + * @return Array containind decoded data. + */ + public static byte[] decode(String encoded) { + + if (encoded == null) { + return null; + } + + char[] base64Data = encoded.toCharArray(); + // remove white spaces + int len = removeWhiteSpace(base64Data); + + if (len % FOURBYTE != 0) { + return null;// should be divisible by four + } + + int numberQuadruple = (len / FOURBYTE); + + if (numberQuadruple == 0) { + return new byte[0]; + } + + byte decodedData[] = null; + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; + char d1 = 0, d2 = 0, d3 = 0, d4 = 0; + + int i = 0; + int encodedIndex = 0; + int dataIndex = 0; + decodedData = new byte[(numberQuadruple) * 3]; + + for (; i < numberQuadruple - 1; i++) { + + if (!isData((d1 = base64Data[dataIndex++])) + || !isData((d2 = base64Data[dataIndex++])) + || !isData((d3 = base64Data[dataIndex++])) + || !isData((d4 = base64Data[dataIndex++]))) { + return null; + }// if found "no data" just return null + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + } + + if (!isData((d1 = base64Data[dataIndex++])) + || !isData((d2 = base64Data[dataIndex++]))) { + return null;// if found "no data" just return null + } + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + + d3 = base64Data[dataIndex++]; + d4 = base64Data[dataIndex++]; + if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters + if (isPad(d3) && isPad(d4)) { + if ((b2 & 0xf) != 0)// last 4 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 1]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + return tmp; + } else if (!isPad(d3) && isPad(d4)) { + b3 = base64Alphabet[d3]; + if ((b3 & 0x3) != 0)// last 2 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 2]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + return tmp; + } else { + return null; + } + } else { // No PAD e.g 3cQl + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + + } + + return decodedData; + } + + /** + * remove WhiteSpace from MIME containing encoded Base64 data. + * + * @param data + * the byte array of base64 data (with WS) + * @return the new length + */ + private static int removeWhiteSpace(char[] data) { + if (data == null) { + return 0; + } + + // count characters that's not whitespace + int newSize = 0; + int len = data.length; + for (int i = 0; i < len; i++) { + if (!isWhiteSpace(data[i])) { + data[newSize++] = data[i]; + } + } + return newSize; + } + + public static void closeIO(Closeable... closeables) { + if (null != closeables && closeables.length > 0) { + for (Closeable closeable : closeables) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (Exception e) { + throw new RuntimeException("", e); + } + } + } + } }