* author: Blankj
@@ -21,6 +24,7 @@ public abstract class BaseItem {
private static final SparseIntArray LAYOUT_SPARSE_ARRAY = new SparseIntArray();
private static final SparseArray VIEW_SPARSE_ARRAY = new SparseArray<>();
+ public boolean isBindViewHolder = false;
static ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
int layoutByType = LAYOUT_SPARSE_ARRAY.get(viewType, -1);
@@ -36,7 +40,11 @@ static ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType
public abstract void bind(@NonNull final ItemViewHolder holder, final int position);
+ public void partialUpdate(List
+ *
+ * @param prefix The prefix of the unique device id.
+ * @param useCache True to use cache, false otherwise.
+ * @return the unique device id
+ */
+ public static String getUniqueDeviceId(String prefix, boolean useCache) {
+ if (!useCache) {
+ return getUniqueDeviceIdReal(prefix);
+ }
if (udid == null) {
synchronized (DeviceUtils.class) {
if (udid == null) {
- final String id = Utils.getSpUtils4Utils().getString(KEY_UDID, null);
+ final String id = UtilsBridge.getSpUtils4Utils().getString(KEY_UDID, null);
if (id != null) {
udid = id;
return udid;
}
- try {
- final String androidId = getAndroidID();
- if (!TextUtils.isEmpty(androidId)) {
- return saveUdid(prefix + 2, androidId);
- }
-
- } catch (Exception ignore) {/**/}
- return saveUdid(prefix + 9, "");
+ return getUniqueDeviceIdReal(prefix);
}
}
}
return udid;
}
- @SuppressLint({"MissingPermission", "HardwareIds"})
+ private static String getUniqueDeviceIdReal(String prefix) {
+ try {
+ final String androidId = getAndroidID();
+ if (!TextUtils.isEmpty(androidId)) {
+ return saveUdid(prefix + 2, androidId);
+ }
+
+ } catch (Exception ignore) {/**/}
+ return saveUdid(prefix + 9, "");
+ }
+
+ @RequiresPermission(allOf = {ACCESS_WIFI_STATE, INTERNET, CHANGE_WIFI_STATE})
public static boolean isSameDevice(final String uniqueDeviceId) {
// {prefix}{type}{32id}
if (TextUtils.isEmpty(uniqueDeviceId) && uniqueDeviceId.length() < 33) return false;
if (uniqueDeviceId.equals(udid)) return true;
- final String cachedId = Utils.getSpUtils4Utils().getString(KEY_UDID, null);
+ final String cachedId = UtilsBridge.getSpUtils4Utils().getString(KEY_UDID, null);
if (uniqueDeviceId.equals(cachedId)) return true;
int st = uniqueDeviceId.length() - 33;
String type = uniqueDeviceId.substring(st, st + 1);
- if (type.startsWith("2")) {
+ if (type.startsWith("1")) {
+ String macAddress = getMacAddress();
+ if (macAddress.equals("")) {
+ return false;
+ }
+ return uniqueDeviceId.substring(st + 1).equals(getUdid("", macAddress));
+ } else if (type.startsWith("2")) {
final String androidId = getAndroidID();
if (TextUtils.isEmpty(androidId)) {
return false;
@@ -446,7 +551,7 @@ public static boolean isSameDevice(final String uniqueDeviceId) {
private static String saveUdid(String prefix, String id) {
udid = getUdid(prefix, id);
- SPUtils.getInstance().put(KEY_UDID, udid);
+ UtilsBridge.getSpUtils4Utils().put(KEY_UDID, udid);
return udid;
}
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncodeUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncodeUtils.java
index 6a491c7c92..a961be77a4 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncodeUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncodeUtils.java
@@ -175,7 +175,6 @@ public static String htmlEncode(final CharSequence input) {
* @param input The input.
* @return the string of decode html-encode string
*/
- @SuppressWarnings("deprecation")
public static CharSequence htmlDecode(final String input) {
if (input == null || input.length() == 0) return "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@@ -191,13 +190,13 @@ public static CharSequence htmlDecode(final String input) {
* @param input The input.
* @return binary string
*/
- public static String binEncode(final String input) {
- StringBuilder stringBuilder = new StringBuilder();
+ public static String binaryEncode(final String input) {
+ if (input == null || input.length() == 0) return "";
+ StringBuilder sb = new StringBuilder();
for (char i : input.toCharArray()) {
- stringBuilder.append(Integer.toBinaryString(i));
- stringBuilder.append(' ');
+ sb.append(Integer.toBinaryString(i)).append(" ");
}
- return stringBuilder.toString();
+ return sb.deleteCharAt(sb.length() - 1).toString();
}
/**
@@ -206,11 +205,12 @@ public static String binEncode(final String input) {
* @param input binary string
* @return UTF-8 String
*/
- public static String binDecode(final String input) {
- String[] splitted = input.split(" ");
+ public static String binaryDecode(final String input) {
+ if (input == null || input.length() == 0) return "";
+ String[] splits = input.split(" ");
StringBuilder sb = new StringBuilder();
- for (String i : splitted) {
- sb.append(((char) Integer.parseInt(i.replace(" ", ""), 2)));
+ for (String split : splits) {
+ sb.append(((char) Integer.parseInt(split, 2)));
}
return sb.toString();
}
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncryptUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncryptUtils.java
index 691ff1f6f0..933f8e4953 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncryptUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/EncryptUtils.java
@@ -1,6 +1,6 @@
package com.blankj.utilcode.util;
-import android.util.Base64;
+import android.os.Build;
import java.io.File;
import java.io.FileInputStream;
@@ -12,15 +12,11 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
-import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
-import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
@@ -63,7 +59,7 @@ public static String encryptMD2ToString(final String data) {
* @return the hex string of MD2 encryption
*/
public static String encryptMD2ToString(final byte[] data) {
- return bytes2HexString(encryptMD2(data));
+ return UtilsBridge.bytes2HexString(encryptMD2(data));
}
/**
@@ -96,9 +92,9 @@ public static String encryptMD5ToString(final String data) {
*/
public static String encryptMD5ToString(final String data, final String salt) {
if (data == null && salt == null) return "";
- if (salt == null) return bytes2HexString(encryptMD5(data.getBytes()));
- if (data == null) return bytes2HexString(encryptMD5(salt.getBytes()));
- return bytes2HexString(encryptMD5((data + salt).getBytes()));
+ if (salt == null) return UtilsBridge.bytes2HexString(encryptMD5(data.getBytes()));
+ if (data == null) return UtilsBridge.bytes2HexString(encryptMD5(salt.getBytes()));
+ return UtilsBridge.bytes2HexString(encryptMD5((data + salt).getBytes()));
}
/**
@@ -108,7 +104,7 @@ public static String encryptMD5ToString(final String data, final String salt) {
* @return the hex string of MD5 encryption
*/
public static String encryptMD5ToString(final byte[] data) {
- return bytes2HexString(encryptMD5(data));
+ return UtilsBridge.bytes2HexString(encryptMD5(data));
}
/**
@@ -120,12 +116,12 @@ public static String encryptMD5ToString(final byte[] data) {
*/
public static String encryptMD5ToString(final byte[] data, final byte[] salt) {
if (data == null && salt == null) return "";
- if (salt == null) return bytes2HexString(encryptMD5(data));
- if (data == null) return bytes2HexString(encryptMD5(salt));
+ if (salt == null) return UtilsBridge.bytes2HexString(encryptMD5(data));
+ if (data == null) return UtilsBridge.bytes2HexString(encryptMD5(salt));
byte[] dataSalt = new byte[data.length + salt.length];
System.arraycopy(data, 0, dataSalt, 0, data.length);
System.arraycopy(salt, 0, dataSalt, data.length, salt.length);
- return bytes2HexString(encryptMD5(dataSalt));
+ return UtilsBridge.bytes2HexString(encryptMD5(dataSalt));
}
/**
@@ -145,7 +141,7 @@ public static byte[] encryptMD5(final byte[] data) {
* @return the hex string of file's MD5 encryption
*/
public static String encryptMD5File2String(final String filePath) {
- File file = isSpace(filePath) ? null : new File(filePath);
+ File file = UtilsBridge.isSpace(filePath) ? null : new File(filePath);
return encryptMD5File2String(file);
}
@@ -156,7 +152,7 @@ public static String encryptMD5File2String(final String filePath) {
* @return the bytes of file's MD5 encryption
*/
public static byte[] encryptMD5File(final String filePath) {
- File file = isSpace(filePath) ? null : new File(filePath);
+ File file = UtilsBridge.isSpace(filePath) ? null : new File(filePath);
return encryptMD5File(file);
}
@@ -167,7 +163,7 @@ public static byte[] encryptMD5File(final String filePath) {
* @return the hex string of file's MD5 encryption
*/
public static String encryptMD5File2String(final File file) {
- return bytes2HexString(encryptMD5File(file));
+ return UtilsBridge.bytes2HexString(encryptMD5File(file));
}
/**
@@ -222,7 +218,7 @@ public static String encryptSHA1ToString(final String data) {
* @return the hex string of SHA1 encryption
*/
public static String encryptSHA1ToString(final byte[] data) {
- return bytes2HexString(encryptSHA1(data));
+ return UtilsBridge.bytes2HexString(encryptSHA1(data));
}
/**
@@ -253,7 +249,7 @@ public static String encryptSHA224ToString(final String data) {
* @return the hex string of SHA224 encryption
*/
public static String encryptSHA224ToString(final byte[] data) {
- return bytes2HexString(encryptSHA224(data));
+ return UtilsBridge.bytes2HexString(encryptSHA224(data));
}
/**
@@ -284,7 +280,7 @@ public static String encryptSHA256ToString(final String data) {
* @return the hex string of SHA256 encryption
*/
public static String encryptSHA256ToString(final byte[] data) {
- return bytes2HexString(encryptSHA256(data));
+ return UtilsBridge.bytes2HexString(encryptSHA256(data));
}
/**
@@ -315,7 +311,7 @@ public static String encryptSHA384ToString(final String data) {
* @return the hex string of SHA384 encryption
*/
public static String encryptSHA384ToString(final byte[] data) {
- return bytes2HexString(encryptSHA384(data));
+ return UtilsBridge.bytes2HexString(encryptSHA384(data));
}
/**
@@ -346,7 +342,7 @@ public static String encryptSHA512ToString(final String data) {
* @return the hex string of SHA512 encryption
*/
public static String encryptSHA512ToString(final byte[] data) {
- return bytes2HexString(encryptSHA512(data));
+ return UtilsBridge.bytes2HexString(encryptSHA512(data));
}
/**
@@ -366,7 +362,7 @@ public static byte[] encryptSHA512(final byte[] data) {
* @param algorithm The name of hash encryption.
* @return the bytes of hash encryption
*/
- private static byte[] hashTemplate(final byte[] data, final String algorithm) {
+ static byte[] hashTemplate(final byte[] data, final String algorithm) {
if (data == null || data.length <= 0) return null;
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
@@ -402,7 +398,7 @@ public static String encryptHmacMD5ToString(final String data, final String key)
* @return the hex string of HmacMD5 encryption
*/
public static String encryptHmacMD5ToString(final byte[] data, final byte[] key) {
- return bytes2HexString(encryptHmacMD5(data, key));
+ return UtilsBridge.bytes2HexString(encryptHmacMD5(data, key));
}
/**
@@ -436,7 +432,7 @@ public static String encryptHmacSHA1ToString(final String data, final String key
* @return the hex string of HmacSHA1 encryption
*/
public static String encryptHmacSHA1ToString(final byte[] data, final byte[] key) {
- return bytes2HexString(encryptHmacSHA1(data, key));
+ return UtilsBridge.bytes2HexString(encryptHmacSHA1(data, key));
}
/**
@@ -470,7 +466,7 @@ public static String encryptHmacSHA224ToString(final String data, final String k
* @return the hex string of HmacSHA224 encryption
*/
public static String encryptHmacSHA224ToString(final byte[] data, final byte[] key) {
- return bytes2HexString(encryptHmacSHA224(data, key));
+ return UtilsBridge.bytes2HexString(encryptHmacSHA224(data, key));
}
/**
@@ -504,7 +500,7 @@ public static String encryptHmacSHA256ToString(final String data, final String k
* @return the hex string of HmacSHA256 encryption
*/
public static String encryptHmacSHA256ToString(final byte[] data, final byte[] key) {
- return bytes2HexString(encryptHmacSHA256(data, key));
+ return UtilsBridge.bytes2HexString(encryptHmacSHA256(data, key));
}
/**
@@ -538,7 +534,7 @@ public static String encryptHmacSHA384ToString(final String data, final String k
* @return the hex string of HmacSHA384 encryption
*/
public static String encryptHmacSHA384ToString(final byte[] data, final byte[] key) {
- return bytes2HexString(encryptHmacSHA384(data, key));
+ return UtilsBridge.bytes2HexString(encryptHmacSHA384(data, key));
}
/**
@@ -572,7 +568,7 @@ public static String encryptHmacSHA512ToString(final String data, final String k
* @return the hex string of HmacSHA512 encryption
*/
public static String encryptHmacSHA512ToString(final byte[] data, final byte[] key) {
- return bytes2HexString(encryptHmacSHA512(data, key));
+ return UtilsBridge.bytes2HexString(encryptHmacSHA512(data, key));
}
/**
@@ -627,7 +623,7 @@ public static byte[] encryptDES2Base64(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return base64Encode(encryptDES(data, key, transformation, iv));
+ return UtilsBridge.base64Encode(encryptDES(data, key, transformation, iv));
}
/**
@@ -644,7 +640,7 @@ public static String encryptDES2HexString(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return bytes2HexString(encryptDES(data, key, transformation, iv));
+ return UtilsBridge.bytes2HexString(encryptDES(data, key, transformation, iv));
}
/**
@@ -678,7 +674,7 @@ public static byte[] decryptBase64DES(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return decryptDES(base64Decode(data), key, transformation, iv);
+ return decryptDES(UtilsBridge.base64Decode(data), key, transformation, iv);
}
/**
@@ -695,7 +691,7 @@ public static byte[] decryptHexStringDES(final String data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return decryptDES(hexString2Bytes(data), key, transformation, iv);
+ return decryptDES(UtilsBridge.hexString2Bytes(data), key, transformation, iv);
}
/**
@@ -733,7 +729,7 @@ public static byte[] encrypt3DES2Base64(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return base64Encode(encrypt3DES(data, key, transformation, iv));
+ return UtilsBridge.base64Encode(encrypt3DES(data, key, transformation, iv));
}
/**
@@ -750,7 +746,7 @@ public static String encrypt3DES2HexString(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return bytes2HexString(encrypt3DES(data, key, transformation, iv));
+ return UtilsBridge.bytes2HexString(encrypt3DES(data, key, transformation, iv));
}
/**
@@ -784,7 +780,7 @@ public static byte[] decryptBase64_3DES(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return decrypt3DES(base64Decode(data), key, transformation, iv);
+ return decrypt3DES(UtilsBridge.base64Decode(data), key, transformation, iv);
}
/**
@@ -801,7 +797,7 @@ public static byte[] decryptHexString3DES(final String data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return decrypt3DES(hexString2Bytes(data), key, transformation, iv);
+ return decrypt3DES(UtilsBridge.hexString2Bytes(data), key, transformation, iv);
}
/**
@@ -839,7 +835,7 @@ public static byte[] encryptAES2Base64(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return base64Encode(encryptAES(data, key, transformation, iv));
+ return UtilsBridge.base64Encode(encryptAES(data, key, transformation, iv));
}
/**
@@ -856,7 +852,7 @@ public static String encryptAES2HexString(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return bytes2HexString(encryptAES(data, key, transformation, iv));
+ return UtilsBridge.bytes2HexString(encryptAES(data, key, transformation, iv));
}
/**
@@ -890,7 +886,7 @@ public static byte[] decryptBase64AES(final byte[] data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return decryptAES(base64Decode(data), key, transformation, iv);
+ return decryptAES(UtilsBridge.base64Decode(data), key, transformation, iv);
}
/**
@@ -907,7 +903,7 @@ public static byte[] decryptHexStringAES(final String data,
final byte[] key,
final String transformation,
final byte[] iv) {
- return decryptAES(hexString2Bytes(data), key, transformation, iv);
+ return decryptAES(UtilsBridge.hexString2Bytes(data), key, transformation, iv);
}
/**
@@ -984,7 +980,7 @@ public static byte[] encryptRSA2Base64(final byte[] data,
final byte[] publicKey,
final int keySize,
final String transformation) {
- return base64Encode(encryptRSA(data, publicKey, keySize, transformation));
+ return UtilsBridge.base64Encode(encryptRSA(data, publicKey, keySize, transformation));
}
/**
@@ -1000,7 +996,7 @@ public static String encryptRSA2HexString(final byte[] data,
final byte[] publicKey,
final int keySize,
final String transformation) {
- return bytes2HexString(encryptRSA(data, publicKey, keySize, transformation));
+ return UtilsBridge.bytes2HexString(encryptRSA(data, publicKey, keySize, transformation));
}
/**
@@ -1032,7 +1028,7 @@ public static byte[] decryptBase64RSA(final byte[] data,
final byte[] privateKey,
final int keySize,
final String transformation) {
- return decryptRSA(base64Decode(data), privateKey, keySize, transformation);
+ return decryptRSA(UtilsBridge.base64Decode(data), privateKey, keySize, transformation);
}
/**
@@ -1048,7 +1044,7 @@ public static byte[] decryptHexStringRSA(final String data,
final byte[] privateKey,
final int keySize,
final String transformation) {
- return decryptRSA(hexString2Bytes(data), privateKey, keySize, transformation);
+ return decryptRSA(UtilsBridge.hexString2Bytes(data), privateKey, keySize, transformation);
}
/**
@@ -1087,12 +1083,18 @@ private static byte[] rsaTemplate(final byte[] data,
}
try {
Key rsaKey;
+ KeyFactory keyFactory;
+ if (Build.VERSION.SDK_INT < 28) {
+ keyFactory = KeyFactory.getInstance("RSA", "BC");
+ } else {
+ keyFactory = KeyFactory.getInstance("RSA");
+ }
if (isEncrypt) {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
- rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec);
+ rsaKey = keyFactory.generatePublic(keySpec);
} else {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
- rsaKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
+ rsaKey = keyFactory.generatePrivate(keySpec);
}
if (rsaKey == null) return null;
Cipher cipher = Cipher.getInstance(transformation);
@@ -1125,17 +1127,7 @@ private static byte[] rsaTemplate(final byte[] data,
} else {
return cipher.doFinal(data);
}
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (NoSuchPaddingException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- } catch (BadPaddingException e) {
- e.printStackTrace();
- } catch (IllegalBlockSizeException e) {
- e.printStackTrace();
- } catch (InvalidKeySpecException e) {
+ } catch (Exception e) {
e.printStackTrace();
}
return null;
@@ -1183,72 +1175,10 @@ public static byte[] rc4(byte[] data, byte[] key) {
return ret;
}
- ///////////////////////////////////////////////////////////////////////////
- // other utils methods
- ///////////////////////////////////////////////////////////////////////////
-
private static byte[] joins(final byte[] prefix, final byte[] suffix) {
byte[] ret = new byte[prefix.length + suffix.length];
System.arraycopy(prefix, 0, ret, 0, prefix.length);
System.arraycopy(suffix, 0, ret, prefix.length, suffix.length);
return ret;
}
-
- private static final char[] HEX_DIGITS =
- {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
- private static String bytes2HexString(final byte[] bytes) {
- if (bytes == null) return "";
- int len = bytes.length;
- if (len <= 0) return "";
- char[] ret = new char[len << 1];
- for (int i = 0, j = 0; i < len; i++) {
- ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f];
- ret[j++] = HEX_DIGITS[bytes[i] & 0x0f];
- }
- return new String(ret);
- }
-
- private static byte[] hexString2Bytes(String hexString) {
- if (isSpace(hexString)) return null;
- int len = hexString.length();
- if (len % 2 != 0) {
- hexString = "0" + hexString;
- len = len + 1;
- }
- char[] hexBytes = hexString.toUpperCase().toCharArray();
- byte[] ret = new byte[len >> 1];
- for (int i = 0; i < len; i += 2) {
- ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1]));
- }
- return ret;
- }
-
- private static int hex2Dec(final char hexChar) {
- if (hexChar >= '0' && hexChar <= '9') {
- return hexChar - '0';
- } else if (hexChar >= 'A' && hexChar <= 'F') {
- return hexChar - 'A' + 10;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- private static byte[] base64Encode(final byte[] input) {
- return Base64.encode(input, Base64.NO_WRAP);
- }
-
- private static byte[] base64Decode(final byte[] input) {
- return Base64.decode(input, Base64.NO_WRAP);
- }
-
- private static boolean isSpace(final String s) {
- if (s == null) return true;
- for (int i = 0, len = s.length(); i < len; ++i) {
- if (!Character.isWhitespace(s.charAt(i))) {
- return false;
- }
- }
- return true;
- }
}
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileIOUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileIOUtils.java
index b40565aa16..ca786e0b98 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileIOUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileIOUtils.java
@@ -1,5 +1,7 @@
package com.blankj.utilcode.util;
+import android.util.Log;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
@@ -51,7 +53,7 @@ private FileIOUtils() {
* @return {@code true}: success {@code false}: fail
*/
public static boolean writeFileFromIS(final String filePath, final InputStream is) {
- return writeFileFromIS(getFileByPath(filePath), is, false, null);
+ return writeFileFromIS(UtilsBridge.getFileByPath(filePath), is, false, null);
}
/**
@@ -65,7 +67,7 @@ public static boolean writeFileFromIS(final String filePath, final InputStream i
public static boolean writeFileFromIS(final String filePath,
final InputStream is,
final boolean append) {
- return writeFileFromIS(getFileByPath(filePath), is, append, null);
+ return writeFileFromIS(UtilsBridge.getFileByPath(filePath), is, append, null);
}
/**
@@ -108,7 +110,7 @@ public static boolean writeFileFromIS(final File file,
public static boolean writeFileFromIS(final String filePath,
final InputStream is,
final OnProgressUpdateListener listener) {
- return writeFileFromIS(getFileByPath(filePath), is, false, listener);
+ return writeFileFromIS(UtilsBridge.getFileByPath(filePath), is, false, listener);
}
/**
@@ -124,7 +126,7 @@ public static boolean writeFileFromIS(final String filePath,
final InputStream is,
final boolean append,
final OnProgressUpdateListener listener) {
- return writeFileFromIS(getFileByPath(filePath), is, append, listener);
+ return writeFileFromIS(UtilsBridge.getFileByPath(filePath), is, append, listener);
}
/**
@@ -154,7 +156,10 @@ public static boolean writeFileFromIS(final File file,
final InputStream is,
final boolean append,
final OnProgressUpdateListener listener) {
- if (is == null || !createOrExistsFile(file)) return false;
+ if (is == null || !UtilsBridge.createOrExistsFile(file)) {
+ Log.e("FileIOUtils", "create file <" + file + "> failed.");
+ return false;
+ }
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(file, append), sBufferSize);
@@ -207,7 +212,7 @@ public static boolean writeFileFromIS(final File file,
* @return {@code true}: success {@code false}: fail
*/
public static boolean writeFileFromBytesByStream(final String filePath, final byte[] bytes) {
- return writeFileFromBytesByStream(getFileByPath(filePath), bytes, false, null);
+ return writeFileFromBytesByStream(UtilsBridge.getFileByPath(filePath), bytes, false, null);
}
/**
@@ -221,7 +226,7 @@ public static boolean writeFileFromBytesByStream(final String filePath, final by
public static boolean writeFileFromBytesByStream(final String filePath,
final byte[] bytes,
final boolean append) {
- return writeFileFromBytesByStream(getFileByPath(filePath), bytes, append, null);
+ return writeFileFromBytesByStream(UtilsBridge.getFileByPath(filePath), bytes, append, null);
}
/**
@@ -264,7 +269,7 @@ public static boolean writeFileFromBytesByStream(final File file,
public static boolean writeFileFromBytesByStream(final String filePath,
final byte[] bytes,
final OnProgressUpdateListener listener) {
- return writeFileFromBytesByStream(getFileByPath(filePath), bytes, false, listener);
+ return writeFileFromBytesByStream(UtilsBridge.getFileByPath(filePath), bytes, false, listener);
}
/**
@@ -280,7 +285,7 @@ public static boolean writeFileFromBytesByStream(final String filePath,
final byte[] bytes,
final boolean append,
final OnProgressUpdateListener listener) {
- return writeFileFromBytesByStream(getFileByPath(filePath), bytes, append, listener);
+ return writeFileFromBytesByStream(UtilsBridge.getFileByPath(filePath), bytes, append, listener);
}
/**
@@ -325,7 +330,7 @@ public static boolean writeFileFromBytesByStream(final File file,
public static boolean writeFileFromBytesByChannel(final String filePath,
final byte[] bytes,
final boolean isForce) {
- return writeFileFromBytesByChannel(getFileByPath(filePath), bytes, false, isForce);
+ return writeFileFromBytesByChannel(UtilsBridge.getFileByPath(filePath), bytes, false, isForce);
}
/**
@@ -341,7 +346,7 @@ public static boolean writeFileFromBytesByChannel(final String filePath,
final byte[] bytes,
final boolean append,
final boolean isForce) {
- return writeFileFromBytesByChannel(getFileByPath(filePath), bytes, append, isForce);
+ return writeFileFromBytesByChannel(UtilsBridge.getFileByPath(filePath), bytes, append, isForce);
}
/**
@@ -371,10 +376,21 @@ public static boolean writeFileFromBytesByChannel(final File file,
final byte[] bytes,
final boolean append,
final boolean isForce) {
- if (bytes == null || !createOrExistsFile(file)) return false;
+ if (bytes == null) {
+ Log.e("FileIOUtils", "bytes is null.");
+ return false;
+ }
+ if (!UtilsBridge.createOrExistsFile(file)) {
+ Log.e("FileIOUtils", "create file <" + file + "> failed.");
+ return false;
+ }
FileChannel fc = null;
try {
fc = new FileOutputStream(file, append).getChannel();
+ if (fc == null) {
+ Log.e("FileIOUtils", "fc is null.");
+ return false;
+ }
fc.position(fc.size());
fc.write(ByteBuffer.wrap(bytes));
if (isForce) fc.force(true);
@@ -420,7 +436,7 @@ public static boolean writeFileFromBytesByMap(final String filePath,
final byte[] bytes,
final boolean append,
final boolean isForce) {
- return writeFileFromBytesByMap(getFileByPath(filePath), bytes, append, isForce);
+ return writeFileFromBytesByMap(UtilsBridge.getFileByPath(filePath), bytes, append, isForce);
}
/**
@@ -450,10 +466,17 @@ public static boolean writeFileFromBytesByMap(final File file,
final byte[] bytes,
final boolean append,
final boolean isForce) {
- if (bytes == null || !createOrExistsFile(file)) return false;
+ if (bytes == null || !UtilsBridge.createOrExistsFile(file)) {
+ Log.e("FileIOUtils", "create file <" + file + "> failed.");
+ return false;
+ }
FileChannel fc = null;
try {
fc = new FileOutputStream(file, append).getChannel();
+ if (fc == null) {
+ Log.e("FileIOUtils", "fc is null.");
+ return false;
+ }
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, fc.size(), bytes.length);
mbb.put(bytes);
if (isForce) mbb.force();
@@ -480,7 +503,7 @@ public static boolean writeFileFromBytesByMap(final File file,
* @return {@code true}: success {@code false}: fail
*/
public static boolean writeFileFromString(final String filePath, final String content) {
- return writeFileFromString(getFileByPath(filePath), content, false);
+ return writeFileFromString(UtilsBridge.getFileByPath(filePath), content, false);
}
/**
@@ -494,7 +517,7 @@ public static boolean writeFileFromString(final String filePath, final String co
public static boolean writeFileFromString(final String filePath,
final String content,
final boolean append) {
- return writeFileFromString(getFileByPath(filePath), content, append);
+ return writeFileFromString(UtilsBridge.getFileByPath(filePath), content, append);
}
/**
@@ -520,7 +543,10 @@ public static boolean writeFileFromString(final File file,
final String content,
final boolean append) {
if (file == null || content == null) return false;
- if (!createOrExistsFile(file)) return false;
+ if (!UtilsBridge.createOrExistsFile(file)) {
+ Log.e("FileIOUtils", "create file <" + file + "> failed.");
+ return false;
+ }
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file, append));
@@ -551,7 +577,7 @@ public static boolean writeFileFromString(final File file,
* @return the lines in file
*/
public static List readFile2List(final String filePath) {
- return readFile2List(getFileByPath(filePath), null);
+ return readFile2List(UtilsBridge.getFileByPath(filePath), null);
}
/**
@@ -562,7 +588,7 @@ public static List readFile2List(final String filePath) {
* @return the lines in file
*/
public static List readFile2List(final String filePath, final String charsetName) {
- return readFile2List(getFileByPath(filePath), charsetName);
+ return readFile2List(UtilsBridge.getFileByPath(filePath), charsetName);
}
/**
@@ -595,7 +621,7 @@ public static List readFile2List(final File file, final String charsetNa
* @return the lines in file
*/
public static List readFile2List(final String filePath, final int st, final int end) {
- return readFile2List(getFileByPath(filePath), st, end, null);
+ return readFile2List(UtilsBridge.getFileByPath(filePath), st, end, null);
}
/**
@@ -611,7 +637,7 @@ public static List readFile2List(final String filePath,
final int st,
final int end,
final String charsetName) {
- return readFile2List(getFileByPath(filePath), st, end, charsetName);
+ return readFile2List(UtilsBridge.getFileByPath(filePath), st, end, charsetName);
}
/**
@@ -639,14 +665,14 @@ public static List readFile2List(final File file,
final int st,
final int end,
final String charsetName) {
- if (!isFileExists(file)) return null;
+ if (!UtilsBridge.isFileExists(file)) return null;
if (st > end) return null;
BufferedReader reader = null;
try {
String line;
int curLine = 1;
List list = new ArrayList<>();
- if (isSpace(charsetName)) {
+ if (UtilsBridge.isSpace(charsetName)) {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
} else {
reader = new BufferedReader(
@@ -680,7 +706,7 @@ public static List readFile2List(final File file,
* @return the string in file
*/
public static String readFile2String(final String filePath) {
- return readFile2String(getFileByPath(filePath), null);
+ return readFile2String(UtilsBridge.getFileByPath(filePath), null);
}
/**
@@ -691,7 +717,7 @@ public static String readFile2String(final String filePath) {
* @return the string in file
*/
public static String readFile2String(final String filePath, final String charsetName) {
- return readFile2String(getFileByPath(filePath), charsetName);
+ return readFile2String(UtilsBridge.getFileByPath(filePath), charsetName);
}
/**
@@ -714,7 +740,7 @@ public static String readFile2String(final File file) {
public static String readFile2String(final File file, final String charsetName) {
byte[] bytes = readFile2BytesByStream(file);
if (bytes == null) return null;
- if (isSpace(charsetName)) {
+ if (UtilsBridge.isSpace(charsetName)) {
return new String(bytes);
} else {
try {
@@ -737,7 +763,7 @@ public static String readFile2String(final File file, final String charsetName)
* @return the bytes in file
*/
public static byte[] readFile2BytesByStream(final String filePath) {
- return readFile2BytesByStream(getFileByPath(filePath), null);
+ return readFile2BytesByStream(UtilsBridge.getFileByPath(filePath), null);
}
/**
@@ -763,7 +789,7 @@ public static byte[] readFile2BytesByStream(final File file) {
*/
public static byte[] readFile2BytesByStream(final String filePath,
final OnProgressUpdateListener listener) {
- return readFile2BytesByStream(getFileByPath(filePath));
+ return readFile2BytesByStream(UtilsBridge.getFileByPath(filePath), listener);
}
/**
@@ -775,7 +801,7 @@ public static byte[] readFile2BytesByStream(final String filePath,
*/
public static byte[] readFile2BytesByStream(final File file,
final OnProgressUpdateListener listener) {
- if (!isFileExists(file)) return null;
+ if (!UtilsBridge.isFileExists(file)) return null;
try {
ByteArrayOutputStream os = null;
InputStream is = new BufferedInputStream(new FileInputStream(file), sBufferSize);
@@ -828,7 +854,7 @@ public static byte[] readFile2BytesByStream(final File file,
* @return the bytes in file
*/
public static byte[] readFile2BytesByChannel(final String filePath) {
- return readFile2BytesByChannel(getFileByPath(filePath));
+ return readFile2BytesByChannel(UtilsBridge.getFileByPath(filePath));
}
/**
@@ -838,10 +864,14 @@ public static byte[] readFile2BytesByChannel(final String filePath) {
* @return the bytes in file
*/
public static byte[] readFile2BytesByChannel(final File file) {
- if (!isFileExists(file)) return null;
+ if (!UtilsBridge.isFileExists(file)) return null;
FileChannel fc = null;
try {
fc = new RandomAccessFile(file, "r").getChannel();
+ if (fc == null) {
+ Log.e("FileIOUtils", "fc is null.");
+ return new byte[0];
+ }
ByteBuffer byteBuffer = ByteBuffer.allocate((int) fc.size());
while (true) {
if (!((fc.read(byteBuffer)) > 0)) break;
@@ -868,7 +898,7 @@ public static byte[] readFile2BytesByChannel(final File file) {
* @return the bytes in file
*/
public static byte[] readFile2BytesByMap(final String filePath) {
- return readFile2BytesByMap(getFileByPath(filePath));
+ return readFile2BytesByMap(UtilsBridge.getFileByPath(filePath));
}
/**
@@ -878,10 +908,14 @@ public static byte[] readFile2BytesByMap(final String filePath) {
* @return the bytes in file
*/
public static byte[] readFile2BytesByMap(final File file) {
- if (!isFileExists(file)) return null;
+ if (!UtilsBridge.isFileExists(file)) return null;
FileChannel fc = null;
try {
fc = new RandomAccessFile(file, "r").getChannel();
+ if (fc == null) {
+ Log.e("FileIOUtils", "fc is null.");
+ return new byte[0];
+ }
int size = (int) fc.size();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
byte[] result = new byte[size];
@@ -911,81 +945,7 @@ public static void setBufferSize(final int bufferSize) {
sBufferSize = bufferSize;
}
- ///////////////////////////////////////////////////////////////////////////
- // other utils methods
- ///////////////////////////////////////////////////////////////////////////
-
- private static File getFileByPath(final String filePath) {
- return isSpace(filePath) ? null : new File(filePath);
- }
-
- private static boolean createOrExistsFile(final String filePath) {
- return createOrExistsFile(getFileByPath(filePath));
- }
-
- private static boolean createOrExistsFile(final File file) {
- if (file == null) return false;
- if (file.exists()) return file.isFile();
- if (!createOrExistsDir(file.getParentFile())) return false;
- try {
- return file.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- private static boolean createOrExistsDir(final File file) {
- return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
- }
-
- private static boolean isFileExists(final File file) {
- return file != null && file.exists();
- }
-
- private static boolean isSpace(final String s) {
- if (s == null) return true;
- for (int i = 0, len = s.length(); i < len; ++i) {
- if (!Character.isWhitespace(s.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- private static byte[] is2Bytes(final InputStream is) {
- if (is == null) return null;
- ByteArrayOutputStream os = null;
- try {
- os = new ByteArrayOutputStream();
- byte[] b = new byte[sBufferSize];
- int len;
- while ((len = is.read(b, 0, sBufferSize)) != -1) {
- os.write(b, 0, len);
- }
- return os.toByteArray();
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- try {
- if (os != null) {
- os.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
public interface OnProgressUpdateListener {
-
void onProgressUpdate(double progress);
-
}
}
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileUtils.java
index 512f2e920a..1acca1e050 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FileUtils.java
@@ -5,17 +5,16 @@
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.os.Build;
+import android.os.StatFs;
+import android.text.TextUtils;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
@@ -24,7 +23,6 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import java.util.Locale;
import javax.net.ssl.HttpsURLConnection;
@@ -51,7 +49,21 @@ private FileUtils() {
* @return the file
*/
public static File getFileByPath(final String filePath) {
- return isSpace(filePath) ? null : new File(filePath);
+ return UtilsBridge.isSpace(filePath) ? null : new File(filePath);
+ }
+
+ /**
+ * Return whether the file exists.
+ *
+ * @param file The file.
+ * @return {@code true}: yes {@code false}: no
+ */
+ public static boolean isFileExists(final File file) {
+ if (file == null) return false;
+ if (file.exists()) {
+ return true;
+ }
+ return isFileExists(file.getAbsolutePath());
}
/**
@@ -61,9 +73,16 @@ public static File getFileByPath(final String filePath) {
* @return {@code true}: yes {@code false}: no
*/
public static boolean isFileExists(final String filePath) {
- if (Build.VERSION.SDK_INT < 29) {
- return isFileExists(getFileByPath(filePath));
- } else {
+ File file = getFileByPath(filePath);
+ if (file == null) return false;
+ if (file.exists()) {
+ return true;
+ }
+ return isFileExistsApi29(filePath);
+ }
+
+ private static boolean isFileExistsApi29(String filePath) {
+ if (Build.VERSION.SDK_INT >= 29) {
try {
Uri uri = Uri.parse(filePath);
ContentResolver cr = Utils.getApp().getContentResolver();
@@ -78,16 +97,7 @@ public static boolean isFileExists(final String filePath) {
}
return true;
}
- }
-
- /**
- * Return whether the file exists.
- *
- * @param file The file.
- * @return {@code true}: yes {@code false}: no
- */
- public static boolean isFileExists(final File file) {
- return file != null && file.exists();
+ return false;
}
/**
@@ -114,7 +124,7 @@ public static boolean rename(final File file, final String newName) {
// file doesn't exist then return false
if (!file.exists()) return false;
// the new name is space then return false
- if (isSpace(newName)) return false;
+ if (UtilsBridge.isSpace(newName)) return false;
// the new name equals old name then return true
if (newName.equals(file.getName())) return true;
File newFile = new File(file.getParent() + File.separator + newName);
@@ -420,12 +430,14 @@ private static boolean copyOrMoveDir(final File srcDir,
if (!srcDir.exists() || !srcDir.isDirectory()) return false;
if (!createOrExistsDir(destDir)) return false;
File[] files = srcDir.listFiles();
- for (File file : files) {
- File oneDestFile = new File(destPath + file.getName());
- if (file.isFile()) {
- if (!copyOrMoveFile(file, oneDestFile, listener, isMove)) return false;
- } else if (file.isDirectory()) {
- if (!copyOrMoveDir(file, oneDestFile, listener, isMove)) return false;
+ if (files != null && files.length > 0) {
+ for (File file : files) {
+ File oneDestFile = new File(destPath + file.getName());
+ if (file.isFile()) {
+ if (!copyOrMoveFile(file, oneDestFile, listener, isMove)) return false;
+ } else if (file.isDirectory()) {
+ if (!copyOrMoveDir(file, oneDestFile, listener, isMove)) return false;
+ }
}
}
return !isMove || deleteDir(srcDir);
@@ -451,7 +463,7 @@ private static boolean copyOrMoveFile(final File srcFile,
}
if (!createOrExistsDir(destFile.getParentFile())) return false;
try {
- return writeFileFromIS(destFile, new FileInputStream(srcFile))
+ return UtilsBridge.writeFileFromIS(destFile.getAbsolutePath(), new FileInputStream(srcFile))
&& !(isMove && !deleteFile(srcFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
@@ -496,7 +508,7 @@ private static boolean deleteDir(final File dir) {
// dir isn't a directory then return false
if (!dir.isDirectory()) return false;
File[] files = dir.listFiles();
- if (files != null && files.length != 0) {
+ if (files != null && files.length > 0) {
for (File file : files) {
if (file.isFile()) {
if (!file.delete()) return false;
@@ -639,7 +651,7 @@ public static List listFilesInDir(final File dir) {
* @return the files in directory
*/
public static List listFilesInDir(final String dirPath, Comparator comparator) {
- return listFilesInDir(getFileByPath(dirPath), false);
+ return listFilesInDir(getFileByPath(dirPath), false, comparator);
}
/**
@@ -836,7 +848,7 @@ private static List listFilesInDirWithFilterInner(final File dir,
List list = new ArrayList<>();
if (!isDir(dir)) return list;
File[] files = dir.listFiles();
- if (files != null && files.length != 0) {
+ if (files != null && files.length > 0) {
for (File file : files) {
if (filter.accept(file)) {
list.add(file);
@@ -1111,7 +1123,7 @@ public static String getSize(final File file) {
*/
private static String getDirSize(final File dir) {
long len = getDirLength(dir);
- return len == -1 ? "" : byte2FitMemorySize(len);
+ return len == -1 ? "" : UtilsBridge.byte2FitMemorySize(len);
}
/**
@@ -1122,7 +1134,7 @@ private static String getDirSize(final File dir) {
*/
private static String getFileSize(final File file) {
long len = getFileLength(file);
- return len == -1 ? "" : byte2FitMemorySize(len);
+ return len == -1 ? "" : UtilsBridge.byte2FitMemorySize(len);
}
/**
@@ -1156,10 +1168,10 @@ public static long getLength(final File file) {
* @return the length of directory
*/
private static long getDirLength(final File dir) {
- if (!isDir(dir)) return -1;
+ if (!isDir(dir)) return 0;
long len = 0;
File[] files = dir.listFiles();
- if (files != null && files.length != 0) {
+ if (files != null && files.length > 0) {
for (File file : files) {
if (file.isDirectory()) {
len += getDirLength(file);
@@ -1213,7 +1225,7 @@ private static long getFileLength(final File file) {
* @return the md5 of file
*/
public static String getFileMD5ToString(final String filePath) {
- File file = isSpace(filePath) ? null : new File(filePath);
+ File file = UtilsBridge.isSpace(filePath) ? null : new File(filePath);
return getFileMD5ToString(file);
}
@@ -1224,7 +1236,7 @@ public static String getFileMD5ToString(final String filePath) {
* @return the md5 of file
*/
public static String getFileMD5ToString(final File file) {
- return bytes2HexString(getFileMD5(file));
+ return UtilsBridge.bytes2HexString(getFileMD5(file));
}
/**
@@ -1288,7 +1300,7 @@ public static String getDirName(final File file) {
* @return the file's path of directory
*/
public static String getDirName(final String filePath) {
- if (isSpace(filePath)) return "";
+ if (UtilsBridge.isSpace(filePath)) return "";
int lastSep = filePath.lastIndexOf(File.separator);
return lastSep == -1 ? "" : filePath.substring(0, lastSep + 1);
}
@@ -1311,7 +1323,7 @@ public static String getFileName(final File file) {
* @return the name of file
*/
public static String getFileName(final String filePath) {
- if (isSpace(filePath)) return "";
+ if (UtilsBridge.isSpace(filePath)) return "";
int lastSep = filePath.lastIndexOf(File.separator);
return lastSep == -1 ? filePath : filePath.substring(lastSep + 1);
}
@@ -1334,7 +1346,7 @@ public static String getFileNameNoExtension(final File file) {
* @return the name of file without extension
*/
public static String getFileNameNoExtension(final String filePath) {
- if (isSpace(filePath)) return "";
+ if (UtilsBridge.isSpace(filePath)) return "";
int lastPoi = filePath.lastIndexOf('.');
int lastSep = filePath.lastIndexOf(File.separator);
if (lastSep == -1) {
@@ -1364,13 +1376,22 @@ public static String getFileExtension(final File file) {
* @return the extension of file
*/
public static String getFileExtension(final String filePath) {
- if (isSpace(filePath)) return "";
+ if (UtilsBridge.isSpace(filePath)) return "";
int lastPoi = filePath.lastIndexOf('.');
int lastSep = filePath.lastIndexOf(File.separator);
if (lastPoi == -1 || lastSep >= lastPoi) return "";
return filePath.substring(lastPoi + 1);
}
+ /**
+ * Notify system to scan the file.
+ *
+ * @param filePath The path of file.
+ */
+ public static void notifySystemToScan(final String filePath) {
+ notifySystemToScan(getFileByPath(filePath));
+ }
+
/**
* Notify system to scan the file.
*
@@ -1379,18 +1400,50 @@ public static String getFileExtension(final String filePath) {
public static void notifySystemToScan(final File file) {
if (file == null || !file.exists()) return;
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
- Uri uri = Uri.fromFile(file);
- intent.setData(uri);
+ intent.setData(Uri.parse("file://" + file.getAbsolutePath()));
Utils.getApp().sendBroadcast(intent);
}
/**
- * Notify system to scan the file.
+ * Return the total size of file system.
*
- * @param filePath The path of file.
+ * @param anyPathInFs Any path in file system.
+ * @return the total size of file system
*/
- public static void notifySystemToScan(final String filePath) {
- notifySystemToScan(getFileByPath(filePath));
+ public static long getFsTotalSize(String anyPathInFs) {
+ if (TextUtils.isEmpty(anyPathInFs)) return 0;
+ StatFs statFs = new StatFs(anyPathInFs);
+ long blockSize;
+ long totalSize;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ blockSize = statFs.getBlockSizeLong();
+ totalSize = statFs.getBlockCountLong();
+ } else {
+ blockSize = statFs.getBlockSize();
+ totalSize = statFs.getBlockCount();
+ }
+ return blockSize * totalSize;
+ }
+
+ /**
+ * Return the available size of file system.
+ *
+ * @param anyPathInFs Any path in file system.
+ * @return the available size of file system
+ */
+ public static long getFsAvailableSize(final String anyPathInFs) {
+ if (TextUtils.isEmpty(anyPathInFs)) return 0;
+ StatFs statFs = new StatFs(anyPathInFs);
+ long blockSize;
+ long availableSize;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ blockSize = statFs.getBlockSizeLong();
+ availableSize = statFs.getAvailableBlocksLong();
+ } else {
+ blockSize = statFs.getBlockSize();
+ availableSize = statFs.getAvailableBlocks();
+ }
+ return blockSize * availableSize;
}
///////////////////////////////////////////////////////////////////////////
@@ -1400,77 +1453,4 @@ public static void notifySystemToScan(final String filePath) {
public interface OnReplaceListener {
boolean onReplace(File srcFile, File destFile);
}
-
- ///////////////////////////////////////////////////////////////////////////
- // other utils methods
- ///////////////////////////////////////////////////////////////////////////
-
- private static final char[] HEX_DIGITS =
- {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
- private static String bytes2HexString(final byte[] bytes) {
- if (bytes == null) return "";
- int len = bytes.length;
- if (len <= 0) return "";
- char[] ret = new char[len << 1];
- for (int i = 0, j = 0; i < len; i++) {
- ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f];
- ret[j++] = HEX_DIGITS[bytes[i] & 0x0f];
- }
- return new String(ret);
- }
-
- private static String byte2FitMemorySize(final long byteNum) {
- if (byteNum < 0) {
- return "shouldn't be less than zero!";
- } else if (byteNum < 1024) {
- return String.format(Locale.getDefault(), "%.3fB", (double) byteNum);
- } else if (byteNum < 1048576) {
- return String.format(Locale.getDefault(), "%.3fKB", (double) byteNum / 1024);
- } else if (byteNum < 1073741824) {
- return String.format(Locale.getDefault(), "%.3fMB", (double) byteNum / 1048576);
- } else {
- return String.format(Locale.getDefault(), "%.3fGB", (double) byteNum / 1073741824);
- }
- }
-
- private static boolean isSpace(final String s) {
- if (s == null) return true;
- for (int i = 0, len = s.length(); i < len; ++i) {
- if (!Character.isWhitespace(s.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean writeFileFromIS(final File file,
- final InputStream is) {
- OutputStream os = null;
- try {
- os = new BufferedOutputStream(new FileOutputStream(file));
- byte[] data = new byte[8192];
- int len;
- while ((len = is.read(data, 0, 8192)) != -1) {
- os.write(data, 0, len);
- }
- return true;
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- try {
- if (os != null) {
- os.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
}
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FlashlightUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FlashlightUtils.java
index 1b864f6ef5..e74996d4e4 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FlashlightUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FlashlightUtils.java
@@ -65,7 +65,7 @@ public static void setFlashlightStatus(final boolean isOn) {
parameters.setFlashMode(FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
} catch (IOException e) {
- Log.e("FlashlightUtils", "setFlashlightStatusOn: ", e);
+ e.printStackTrace();
}
}
} else {
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
index b6c9615309..31bbac1217 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/FragmentUtils.java
@@ -3,23 +3,25 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
-import android.support.annotation.AnimRes;
-import android.support.annotation.AnimatorRes;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IdRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import androidx.annotation.AnimRes;
+import androidx.annotation.AnimatorRes;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
/**
*
* author: Blankj
@@ -301,7 +303,7 @@ public static void add(@NonNull final FragmentManager fm,
final boolean isHide,
final boolean isAddStack) {
putArgs(add, new Args(containerId, tag, isHide, isAddStack));
- operateNoAnim(fm, TYPE_ADD_FRAGMENT, null, add);
+ operateNoAnim(TYPE_ADD_FRAGMENT, fm, null, add);
}
/**
@@ -489,7 +491,7 @@ public static void add(@NonNull final FragmentManager fm,
putArgs(adds[i], new Args(containerId, tags[i], showIndex != i, false));
}
}
- operateNoAnim(fm, TYPE_ADD_FRAGMENT, null, adds);
+ operateNoAnim(TYPE_ADD_FRAGMENT, fm, null, adds);
}
/**
@@ -499,7 +501,7 @@ public static void add(@NonNull final FragmentManager fm,
*/
public static void show(@NonNull final Fragment show) {
putArgs(show, false);
- operateNoAnim(show.getFragmentManager(), TYPE_SHOW_FRAGMENT, null, show);
+ operateNoAnim(TYPE_SHOW_FRAGMENT, show.getFragmentManager(), null, show);
}
/**
@@ -512,11 +514,7 @@ public static void show(@NonNull final FragmentManager fm) {
for (Fragment show : fragments) {
putArgs(show, false);
}
- operateNoAnim(fm,
- TYPE_SHOW_FRAGMENT,
- null,
- fragments.toArray(new Fragment[0])
- );
+ operateNoAnim(TYPE_SHOW_FRAGMENT, fm, null, fragments.toArray(new Fragment[0]));
}
/**
@@ -526,7 +524,7 @@ public static void show(@NonNull final FragmentManager fm) {
*/
public static void hide(@NonNull final Fragment hide) {
putArgs(hide, true);
- operateNoAnim(hide.getFragmentManager(), TYPE_HIDE_FRAGMENT, null, hide);
+ operateNoAnim(TYPE_HIDE_FRAGMENT, hide.getFragmentManager(), null, hide);
}
/**
@@ -539,21 +537,28 @@ public static void hide(@NonNull final FragmentManager fm) {
for (Fragment hide : fragments) {
putArgs(hide, true);
}
- operateNoAnim(fm,
- TYPE_HIDE_FRAGMENT,
- null,
- fragments.toArray(new Fragment[0])
- );
+ operateNoAnim(TYPE_HIDE_FRAGMENT, fm, null, fragments.toArray(new Fragment[0]));
+ }
+
+ /**
+ * Show fragment then hide other fragment.
+ *
+ * @param show The fragment will be show.
+ * @param hide The fragment will be hide.
+ */
+ public static void showHide(@NonNull final Fragment show,
+ @NonNull final Fragment hide) {
+ showHide(show, Collections.singletonList(hide));
}
/**
* Show fragment then hide other fragment.
*
* @param showIndex The index of fragment will be shown.
- * @param fragments The fragments will be hide.
+ * @param fragments The fragment will be hide.
*/
- public static void showHide(final int showIndex, @NonNull final List fragments) {
- showHide(fragments.get(showIndex), fragments);
+ public static void showHide(final int showIndex, @NonNull final Fragment... fragments) {
+ showHide(fragments[showIndex], fragments);
}
/**
@@ -562,22 +567,18 @@ public static void showHide(final int showIndex, @NonNull final List f
* @param show The fragment will be show.
* @param hide The fragment will be hide.
*/
- public static void showHide(@NonNull final Fragment show, @NonNull final List hide) {
- for (Fragment fragment : hide) {
- putArgs(fragment, fragment != show);
- }
- operateNoAnim(show.getFragmentManager(), TYPE_SHOW_HIDE_FRAGMENT, show,
- hide.toArray(new Fragment[0]));
+ public static void showHide(@NonNull final Fragment show, @NonNull final Fragment... hide) {
+ showHide(show, Arrays.asList(hide));
}
/**
* Show fragment then hide other fragment.
*
* @param showIndex The index of fragment will be shown.
- * @param fragments The fragment will be hide.
+ * @param fragments The fragments will be hide.
*/
- public static void showHide(final int showIndex, @NonNull final Fragment... fragments) {
- showHide(fragments[showIndex], fragments);
+ public static void showHide(final int showIndex, @NonNull final List fragments) {
+ showHide(fragments.get(showIndex), fragments);
}
/**
@@ -586,13 +587,14 @@ public static void showHide(final int showIndex, @NonNull final Fragment... frag
* @param show The fragment will be show.
* @param hide The fragment will be hide.
*/
- public static void showHide(@NonNull final Fragment show, @NonNull final Fragment... hide) {
+ public static void showHide(@NonNull final Fragment show, @NonNull final List hide) {
for (Fragment fragment : hide) {
putArgs(fragment, fragment != show);
}
- operateNoAnim(show.getFragmentManager(), TYPE_SHOW_HIDE_FRAGMENT, show, hide);
+ operateNoAnim(TYPE_SHOW_HIDE_FRAGMENT, show.getFragmentManager(), show, hide.toArray(new Fragment[0]));
}
+
/**
* Show fragment then hide other fragment.
*
@@ -600,10 +602,47 @@ public static void showHide(@NonNull final Fragment show, @NonNull final Fragmen
* @param hide The fragment will be hide.
*/
public static void showHide(@NonNull final Fragment show,
- @NonNull final Fragment hide) {
- putArgs(show, false);
- putArgs(hide, true);
- operateNoAnim(show.getFragmentManager(), TYPE_SHOW_HIDE_FRAGMENT, show, hide);
+ @NonNull final Fragment hide, @AnimatorRes @AnimRes final int enterAnim,
+ @AnimatorRes @AnimRes final int exitAnim,
+ @AnimatorRes @AnimRes final int popEnterAnim,
+ @AnimatorRes @AnimRes final int popExitAnim) {
+ showHide(show, Collections.singletonList(hide), enterAnim, exitAnim, popEnterAnim, popExitAnim);
+ }
+
+ /**
+ * Show fragment then hide other fragment.
+ *
+ * @param showIndex The index of fragment will be shown.
+ * @param fragments The fragments will be hide.
+ */
+ public static void showHide(final int showIndex, @NonNull final List fragments,
+ @AnimatorRes @AnimRes final int enterAnim,
+ @AnimatorRes @AnimRes final int exitAnim,
+ @AnimatorRes @AnimRes final int popEnterAnim,
+ @AnimatorRes @AnimRes final int popExitAnim) {
+ showHide(fragments.get(showIndex), fragments, enterAnim, exitAnim, popEnterAnim, popExitAnim);
+ }
+
+ /**
+ * Show fragment then hide other fragment.
+ *
+ * @param show The fragment will be show.
+ * @param hide The fragment will be hide.
+ */
+ public static void showHide(@NonNull final Fragment show, @NonNull final List hide,
+ @AnimatorRes @AnimRes final int enterAnim,
+ @AnimatorRes @AnimRes final int exitAnim,
+ @AnimatorRes @AnimRes final int popEnterAnim,
+ @AnimatorRes @AnimRes final int popExitAnim) {
+ for (Fragment fragment : hide) {
+ putArgs(fragment, fragment != show);
+ }
+ FragmentManager fm = show.getFragmentManager();
+ if (fm != null) {
+ FragmentTransaction ft = fm.beginTransaction();
+ addAnim(ft, enterAnim, exitAnim, popEnterAnim, popExitAnim);
+ operate(TYPE_SHOW_HIDE_FRAGMENT, fm, ft, show, hide.toArray(new Fragment[0]));
+ }
}
/**
@@ -1357,7 +1396,7 @@ public static void popAll(@NonNull final FragmentManager fm, final boolean isImm
* @param remove The fragment will be removed.
*/
public static void remove(@NonNull final Fragment remove) {
- operateNoAnim(remove.getFragmentManager(), TYPE_REMOVE_FRAGMENT, null, remove);
+ operateNoAnim(TYPE_REMOVE_FRAGMENT, remove.getFragmentManager(), null, remove);
}
/**
@@ -1367,8 +1406,7 @@ public static void remove(@NonNull final Fragment remove) {
* @param isIncludeSelf True to include the fragment, false otherwise.
*/
public static void removeTo(@NonNull final Fragment removeTo, final boolean isIncludeSelf) {
- operateNoAnim(removeTo.getFragmentManager(), TYPE_REMOVE_TO_FRAGMENT,
- isIncludeSelf ? removeTo : null, removeTo);
+ operateNoAnim(TYPE_REMOVE_TO_FRAGMENT, removeTo.getFragmentManager(), isIncludeSelf ? removeTo : null, removeTo);
}
/**
@@ -1378,11 +1416,7 @@ public static void removeTo(@NonNull final Fragment removeTo, final boolean isIn
*/
public static void removeAll(@NonNull final FragmentManager fm) {
List fragments = getFragments(fm);
- operateNoAnim(fm,
- TYPE_REMOVE_FRAGMENT,
- null,
- fragments.toArray(new Fragment[0])
- );
+ operateNoAnim(TYPE_REMOVE_FRAGMENT, fm, null, fragments.toArray(new Fragment[0]));
}
private static void putArgs(final Fragment fragment, final Args args) {
@@ -1414,8 +1448,7 @@ private static Args getArgs(final Fragment fragment) {
bundle.getBoolean(ARGS_IS_ADD_STACK));
}
- private static void operateNoAnim(@Nullable final FragmentManager fm,
- final int type,
+ private static void operateNoAnim(final int type, @Nullable final FragmentManager fm,
final Fragment src,
Fragment... dest) {
if (fm == null) return;
@@ -1493,6 +1526,7 @@ private static void operate(final int type,
break;
}
ft.commitAllowingStateLoss();
+ fm.executePendingTransactions();
}
private static void addAnim(final FragmentTransaction ft,
@@ -1542,14 +1576,14 @@ private static Fragment getTopIsInStack(@NonNull final FragmentManager fm,
if (isInStack) {
Bundle args = fragment.getArguments();
if (args != null && args.getBoolean(ARGS_IS_ADD_STACK)) {
- return getTopIsInStack(fragment.getChildFragmentManager(), parentFragment, true);
+ return getTopIsInStack(fragment.getChildFragmentManager(), fragment, true);
}
} else {
- return getTopIsInStack(fragment.getChildFragmentManager(), parentFragment, false);
+ return getTopIsInStack(fragment.getChildFragmentManager(), fragment, false);
}
}
}
- return null;
+ return parentFragment;
}
/**
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/GsonUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/GsonUtils.java
index 2951f9797f..c3eb0684c6 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/GsonUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/GsonUtils.java
@@ -1,5 +1,7 @@
package com.blankj.utilcode.util;
+import android.text.TextUtils;
+
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
@@ -9,6 +11,9 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import androidx.annotation.NonNull;
/**
@@ -21,31 +26,58 @@
*/
public final class GsonUtils {
- private static final Gson GSON = createGson(true);
+ private static final String KEY_DEFAULT = "defaultGson";
+ private static final String KEY_DELEGATE = "delegateGson";
+ private static final String KEY_LOG_UTILS = "logUtilsGson";
- private static final Gson GSON_NO_NULLS = createGson(false);
+ private static final Map GSONS = new ConcurrentHashMap<>();
private GsonUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
- * Gets pre-configured {@link Gson} instance.
+ * Set the delegate of {@link Gson}.
*
- * @return {@link Gson} instance.
+ * @param delegate The delegate of {@link Gson}.
*/
- public static Gson getGson() {
- return getGson(true);
+ public static void setGsonDelegate(Gson delegate) {
+ if (delegate == null) return;
+ GSONS.put(KEY_DELEGATE, delegate);
}
/**
- * Gets pre-configured {@link Gson} instance.
+ * Set the {@link Gson} with key.
*
- * @param serializeNulls Determines if nulls will be serialized.
- * @return {@link Gson} instance.
+ * @param key The key.
+ * @param gson The {@link Gson}.
*/
- public static Gson getGson(final boolean serializeNulls) {
- return serializeNulls ? GSON_NO_NULLS : GSON;
+ public static void setGson(final String key, final Gson gson) {
+ if (TextUtils.isEmpty(key) || gson == null) return;
+ GSONS.put(key, gson);
+ }
+
+ /**
+ * Return the {@link Gson} with key.
+ *
+ * @param key The key.
+ * @return the {@link Gson} with key
+ */
+ public static Gson getGson(final String key) {
+ return GSONS.get(key);
+ }
+
+ public static Gson getGson() {
+ Gson gsonDelegate = GSONS.get(KEY_DELEGATE);
+ if (gsonDelegate != null) {
+ return gsonDelegate;
+ }
+ Gson gsonDefault = GSONS.get(KEY_DEFAULT);
+ if (gsonDefault == null) {
+ gsonDefault = createGson();
+ GSONS.put(KEY_DEFAULT, gsonDefault);
+ }
+ return gsonDefault;
}
/**
@@ -55,86 +87,133 @@ public static Gson getGson(final boolean serializeNulls) {
* @return object serialized into json.
*/
public static String toJson(final Object object) {
- return toJson(object, true);
+ return toJson(getGson(), object);
}
/**
* Serializes an object into json.
*
- * @param object The object to serialize.
- * @param includeNulls Determines if nulls will be included.
+ * @param src The object to serialize.
+ * @param typeOfSrc The specific genericized type of src.
* @return object serialized into json.
*/
- public static String toJson(final Object object, final boolean includeNulls) {
- return includeNulls ? GSON.toJson(object) : GSON_NO_NULLS.toJson(object);
+ public static String toJson(final Object src, @NonNull final Type typeOfSrc) {
+ return toJson(getGson(), src, typeOfSrc);
}
/**
* Serializes an object into json.
*
- * @param src The object to serialize.
- * @param typeOfSrc The specific genericized type of src.
+ * @param gson The gson.
+ * @param object The object to serialize.
* @return object serialized into json.
*/
- public static String toJson(final Object src, final Type typeOfSrc) {
- return toJson(src, typeOfSrc, true);
+ public static String toJson(@NonNull final Gson gson, final Object object) {
+ return gson.toJson(object);
}
/**
* Serializes an object into json.
*
- * @param src The object to serialize.
- * @param typeOfSrc The specific genericized type of src.
- * @param includeNulls Determines if nulls will be included.
+ * @param gson The gson.
+ * @param src The object to serialize.
+ * @param typeOfSrc The specific genericized type of src.
* @return object serialized into json.
*/
- public static String toJson(final Object src, final Type typeOfSrc, final boolean includeNulls) {
- return includeNulls ? GSON.toJson(src, typeOfSrc) : GSON_NO_NULLS.toJson(src, typeOfSrc);
+ public static String toJson(@NonNull final Gson gson, final Object src, @NonNull final Type typeOfSrc) {
+ return gson.toJson(src, typeOfSrc);
+ }
+
+ /**
+ * Converts {@link String} to given type.
+ *
+ * @param json The json to convert.
+ * @param type Type json will be converted to.
+ * @return instance of type
+ */
+ public static T fromJson(final String json, @NonNull final Class type) {
+ return fromJson(getGson(), json, type);
+ }
+
+ /**
+ * Converts {@link String} to given type.
+ *
+ * @param json the json to convert.
+ * @param type type type json will be converted to.
+ * @return instance of type
+ */
+ public static T fromJson(final String json, @NonNull final Type type) {
+ return fromJson(getGson(), json, type);
}
+ /**
+ * Converts {@link Reader} to given type.
+ *
+ * @param reader the reader to convert.
+ * @param type type type json will be converted to.
+ * @return instance of type
+ */
+ public static T fromJson(@NonNull final Reader reader, @NonNull final Class type) {
+ return fromJson(getGson(), reader, type);
+ }
+
+ /**
+ * Converts {@link Reader} to given type.
+ *
+ * @param reader the reader to convert.
+ * @param type type type json will be converted to.
+ * @return instance of type
+ */
+ public static T fromJson(@NonNull final Reader reader, @NonNull final Type type) {
+ return fromJson(getGson(), reader, type);
+ }
/**
* Converts {@link String} to given type.
*
+ * @param gson The gson.
* @param json The json to convert.
* @param type Type json will be converted to.
* @return instance of type
*/
- public static T fromJson(final String json, final Class type) {
- return GSON.fromJson(json, type);
+ public static T fromJson(@NonNull final Gson gson, final String json, @NonNull final Class type) {
+ return gson.fromJson(json, type);
}
/**
* Converts {@link String} to given type.
*
+ * @param gson The gson.
* @param json the json to convert.
* @param type type type json will be converted to.
* @return instance of type
*/
- public static T fromJson(final String json, final Type type) {
- return GSON.fromJson(json, type);
+ public static T fromJson(@NonNull final Gson gson, final String json, @NonNull final Type type) {
+ return gson.fromJson(json, type);
}
/**
* Converts {@link Reader} to given type.
*
+ * @param gson The gson.
* @param reader the reader to convert.
* @param type type type json will be converted to.
* @return instance of type
*/
- public static T fromJson(final Reader reader, final Class type) {
- return GSON.fromJson(reader, type);
+ public static T fromJson(@NonNull final Gson gson, final Reader reader, @NonNull final Class type) {
+ return gson.fromJson(reader, type);
}
/**
* Converts {@link Reader} to given type.
*
+ * @param gson The gson.
* @param reader the reader to convert.
* @param type type type json will be converted to.
* @return instance of type
*/
- public static T fromJson(final Reader reader, final Type type) {
- return GSON.fromJson(reader, type);
+ public static T fromJson(@NonNull final Gson gson, final Reader reader, @NonNull final Type type) {
+ return gson.fromJson(reader, type);
}
/**
@@ -143,7 +222,7 @@ public static T fromJson(final Reader reader, final Type type) {
* @param type The type.
* @return the type of {@link List} with the {@code type}
*/
- public static Type getListType(final Type type) {
+ public static Type getListType(@NonNull final Type type) {
return TypeToken.getParameterized(List.class, type).getType();
}
@@ -153,7 +232,7 @@ public static Type getListType(final Type type) {
* @param type The type.
* @return the type of {@link Set} with the {@code type}
*/
- public static Type getSetType(final Type type) {
+ public static Type getSetType(@NonNull final Type type) {
return TypeToken.getParameterized(Set.class, type).getType();
}
@@ -164,7 +243,7 @@ public static Type getSetType(final Type type) {
* @param valueType The type of value.
* @return the type of map with the {@code keyType} and {@code valueType}
*/
- public static Type getMapType(final Type keyType, final Type valueType) {
+ public static Type getMapType(@NonNull final Type keyType, @NonNull final Type valueType) {
return TypeToken.getParameterized(Map.class, keyType, valueType).getType();
}
@@ -174,7 +253,7 @@ public static Type getMapType(final Type keyType, final Type valueType) {
* @param type The type.
* @return the type of map with the {@code type}
*/
- public static Type getArrayType(final Type type) {
+ public static Type getArrayType(@NonNull final Type type) {
return TypeToken.getArray(type).getType();
}
@@ -185,19 +264,20 @@ public static Type getArrayType(final Type type) {
* @param typeArguments The type of arguments.
* @return the type of map with the {@code type}
*/
- public static Type getType(final Type rawType, final Type... typeArguments) {
+ public static Type getType(@NonNull final Type rawType, @NonNull final Type... typeArguments) {
return TypeToken.getParameterized(rawType, typeArguments).getType();
}
- /**
- * Create a pre-configured {@link Gson} instance.
- *
- * @param serializeNulls determines if nulls will be serialized.
- * @return {@link Gson} instance.
- */
- private static Gson createGson(final boolean serializeNulls) {
- final GsonBuilder builder = new GsonBuilder();
- if (serializeNulls) builder.serializeNulls();
- return builder.create();
+ static Gson getGson4LogUtils() {
+ Gson gson4LogUtils = GSONS.get(KEY_LOG_UTILS);
+ if (gson4LogUtils == null) {
+ gson4LogUtils = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
+ GSONS.put(KEY_LOG_UTILS, gson4LogUtils);
+ }
+ return gson4LogUtils;
+ }
+
+ private static Gson createGson() {
+ return new GsonBuilder().serializeNulls().disableHtmlEscaping().create();
}
}
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java
index c1b6c50f8f..e0d472428f 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/ImageUtils.java
@@ -1,5 +1,7 @@
package com.blankj.utilcode.util;
+import android.Manifest;
+import android.content.ContentValues;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
@@ -12,6 +14,7 @@
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
@@ -22,18 +25,16 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
+import android.net.Uri;
import android.os.Build;
+import android.os.Environment;
+import android.provider.MediaStore;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.RequiresApi;
-import android.support.v4.content.ContextCompat;
+import android.text.TextUtils;
+import android.util.Log;
import android.view.View;
import java.io.BufferedOutputStream;
@@ -46,6 +47,15 @@
import java.io.InputStream;
import java.io.OutputStream;
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.FloatRange;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.core.content.ContextCompat;
+
/**
*
* author: Blankj
@@ -64,13 +74,24 @@ private ImageUtils() {
* Bitmap to bytes.
*
* @param bitmap The bitmap.
- * @param format The format of bitmap.
* @return bytes
*/
- public static byte[] bitmap2Bytes(final Bitmap bitmap, final CompressFormat format) {
+ public static byte[] bitmap2Bytes(final Bitmap bitmap) {
+ return bitmap2Bytes(bitmap, CompressFormat.PNG, 100);
+ }
+
+ /**
+ * Bitmap to bytes.
+ *
+ * @param bitmap The bitmap.
+ * @param format The format of bitmap.
+ * @param quality The quality.
+ * @return bytes
+ */
+ public static byte[] bitmap2Bytes(@Nullable final Bitmap bitmap, @NonNull final CompressFormat format, int quality) {
if (bitmap == null) return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- bitmap.compress(format, 100, baos);
+ bitmap.compress(format, quality, baos);
return baos.toByteArray();
}
@@ -80,7 +101,7 @@ public static byte[] bitmap2Bytes(final Bitmap bitmap, final CompressFormat form
* @param bytes The bytes.
* @return bitmap
*/
- public static Bitmap bytes2Bitmap(final byte[] bytes) {
+ public static Bitmap bytes2Bitmap(@Nullable final byte[] bytes) {
return (bytes == null || bytes.length == 0)
? null
: BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
@@ -92,7 +113,8 @@ public static Bitmap bytes2Bitmap(final byte[] bytes) {
* @param drawable The drawable.
* @return bitmap
*/
- public static Bitmap drawable2Bitmap(final Drawable drawable) {
+ public static Bitmap drawable2Bitmap(@Nullable final Drawable drawable) {
+ if (drawable == null) return null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable.getBitmap() != null) {
@@ -124,10 +146,20 @@ public static Bitmap drawable2Bitmap(final Drawable drawable) {
* @param bitmap The bitmap.
* @return drawable
*/
- public static Drawable bitmap2Drawable(final Bitmap bitmap) {
+ public static Drawable bitmap2Drawable(@Nullable final Bitmap bitmap) {
return bitmap == null ? null : new BitmapDrawable(Utils.getApp().getResources(), bitmap);
}
+ /**
+ * Drawable to bytes.
+ *
+ * @param drawable The drawable.
+ * @return bytes
+ */
+ public static byte[] drawable2Bytes(@Nullable final Drawable drawable) {
+ return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable));
+ }
+
/**
* Drawable to bytes.
*
@@ -135,8 +167,8 @@ public static Drawable bitmap2Drawable(final Bitmap bitmap) {
* @param format The format of bitmap.
* @return bytes
*/
- public static byte[] drawable2Bytes(final Drawable drawable, final CompressFormat format) {
- return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format);
+ public static byte[] drawable2Bytes(final Drawable drawable, final CompressFormat format, int quality) {
+ return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format, quality);
}
/**
@@ -161,18 +193,24 @@ public static Bitmap view2Bitmap(final View view) {
boolean willNotCacheDrawing = view.willNotCacheDrawing();
view.setDrawingCacheEnabled(true);
view.setWillNotCacheDrawing(false);
- final Bitmap drawingCache = view.getDrawingCache();
+ Bitmap drawingCache = view.getDrawingCache();
Bitmap bitmap;
- if (null == drawingCache) {
+ if (null == drawingCache || drawingCache.isRecycled()) {
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache();
- bitmap = Bitmap.createBitmap(view.getDrawingCache());
+ drawingCache = view.getDrawingCache();
+ if (null == drawingCache || drawingCache.isRecycled()) {
+ bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.RGB_565);
+ Canvas canvas = new Canvas(bitmap);
+ view.draw(canvas);
+ } else {
+ bitmap = Bitmap.createBitmap(drawingCache);
+ }
} else {
bitmap = Bitmap.createBitmap(drawingCache);
}
- view.destroyDrawingCache();
view.setWillNotCacheDrawing(willNotCacheDrawing);
view.setDrawingCacheEnabled(drawingCacheEnabled);
return bitmap;
@@ -214,7 +252,7 @@ public static Bitmap getBitmap(final File file, final int maxWidth, final int ma
* @return bitmap
*/
public static Bitmap getBitmap(final String filePath) {
- if (isSpace(filePath)) return null;
+ if (UtilsBridge.isSpace(filePath)) return null;
return BitmapFactory.decodeFile(filePath);
}
@@ -227,7 +265,7 @@ public static Bitmap getBitmap(final String filePath) {
* @return bitmap
*/
public static Bitmap getBitmap(final String filePath, final int maxWidth, final int maxHeight) {
- if (isSpace(filePath)) return null;
+ if (UtilsBridge.isSpace(filePath)) return null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
@@ -257,8 +295,12 @@ public static Bitmap getBitmap(final InputStream is) {
*/
public static Bitmap getBitmap(final InputStream is, final int maxWidth, final int maxHeight) {
if (is == null) return null;
- byte[] bytes = input2Byte(is);
- return getBitmap(bytes, 0, maxWidth, maxHeight);
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(is, null, options);
+ options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
+ options.inJustDecodeBounds = false;
+ return BitmapFactory.decodeStream(is, null, options);
}
/**
@@ -303,6 +345,9 @@ public static Bitmap getBitmap(final byte[] data,
*/
public static Bitmap getBitmap(@DrawableRes final int resId) {
Drawable drawable = ContextCompat.getDrawable(Utils.getApp(), resId);
+ if (drawable == null) {
+ return null;
+ }
Canvas canvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
@@ -753,11 +798,27 @@ public static Bitmap toRoundCorner(final Bitmap src,
*/
public static Bitmap toRoundCorner(final Bitmap src,
final float radius,
- @IntRange(from = 0) int borderSize,
+ @FloatRange(from = 0) float borderSize,
@ColorInt int borderColor) {
return toRoundCorner(src, radius, borderSize, borderColor, false);
}
+ /**
+ * Return the round corner bitmap.
+ *
+ * @param src The source of bitmap.
+ * @param radii Array of 8 values, 4 pairs of [X,Y] radii
+ * @param borderSize The size of border.
+ * @param borderColor The color of border.
+ * @return the round corner bitmap
+ */
+ public static Bitmap toRoundCorner(final Bitmap src,
+ final float[] radii,
+ @FloatRange(from = 0) float borderSize,
+ @ColorInt int borderColor) {
+ return toRoundCorner(src, radii, borderSize, borderColor, false);
+ }
+
/**
* Return the round corner bitmap.
*
@@ -770,7 +831,26 @@ public static Bitmap toRoundCorner(final Bitmap src,
*/
public static Bitmap toRoundCorner(final Bitmap src,
final float radius,
- @IntRange(from = 0) int borderSize,
+ @FloatRange(from = 0) float borderSize,
+ @ColorInt int borderColor,
+ final boolean recycle) {
+ float[] radii = {radius, radius, radius, radius, radius, radius, radius, radius};
+ return toRoundCorner(src, radii, borderSize, borderColor, recycle);
+ }
+
+ /**
+ * Return the round corner bitmap.
+ *
+ * @param src The source of bitmap.
+ * @param radii Array of 8 values, 4 pairs of [X,Y] radii
+ * @param borderSize The size of border.
+ * @param borderColor The color of border.
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the round corner bitmap
+ */
+ public static Bitmap toRoundCorner(final Bitmap src,
+ final float[] radii,
+ @FloatRange(from = 0) float borderSize,
@ColorInt int borderColor,
final boolean recycle) {
if (isEmptyBitmap(src)) return null;
@@ -784,14 +864,16 @@ public static Bitmap toRoundCorner(final Bitmap src,
RectF rectF = new RectF(0, 0, width, height);
float halfBorderSize = borderSize / 2f;
rectF.inset(halfBorderSize, halfBorderSize);
- canvas.drawRoundRect(rectF, radius, radius, paint);
+ Path path = new Path();
+ path.addRoundRect(rectF, radii, Path.Direction.CW);
+ canvas.drawPath(path, paint);
if (borderSize > 0) {
paint.setShader(null);
paint.setColor(borderColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(borderSize);
paint.setStrokeCap(Paint.Cap.ROUND);
- canvas.drawRoundRect(rectF, radius, radius, paint);
+ canvas.drawPath(path, paint);
}
if (recycle && !src.isRecycled() && ret != src) src.recycle();
return ret;
@@ -807,12 +889,46 @@ public static Bitmap toRoundCorner(final Bitmap src,
* @return the round corner bitmap with border
*/
public static Bitmap addCornerBorder(final Bitmap src,
- @IntRange(from = 1) final int borderSize,
+ @FloatRange(from = 1) final float borderSize,
@ColorInt final int color,
@FloatRange(from = 0) final float cornerRadius) {
return addBorder(src, borderSize, color, false, cornerRadius, false);
}
+ /**
+ * Return the round corner bitmap with border.
+ *
+ * @param src The source of bitmap.
+ * @param borderSize The size of border.
+ * @param color The color of border.
+ * @param radii Array of 8 values, 4 pairs of [X,Y] radii
+ * @return the round corner bitmap with border
+ */
+ public static Bitmap addCornerBorder(final Bitmap src,
+ @FloatRange(from = 1) final float borderSize,
+ @ColorInt final int color,
+ final float[] radii) {
+ return addBorder(src, borderSize, color, false, radii, false);
+ }
+
+ /**
+ * Return the round corner bitmap with border.
+ *
+ * @param src The source of bitmap.
+ * @param borderSize The size of border.
+ * @param color The color of border.
+ * @param radii Array of 8 values, 4 pairs of [X,Y] radii
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the round corner bitmap with border
+ */
+ public static Bitmap addCornerBorder(final Bitmap src,
+ @FloatRange(from = 1) final float borderSize,
+ @ColorInt final int color,
+ final float[] radii,
+ final boolean recycle) {
+ return addBorder(src, borderSize, color, false, radii, recycle);
+ }
+
/**
* Return the round corner bitmap with border.
*
@@ -824,7 +940,7 @@ public static Bitmap addCornerBorder(final Bitmap src,
* @return the round corner bitmap with border
*/
public static Bitmap addCornerBorder(final Bitmap src,
- @IntRange(from = 1) final int borderSize,
+ @FloatRange(from = 1) final float borderSize,
@ColorInt final int color,
@FloatRange(from = 0) final float cornerRadius,
final boolean recycle) {
@@ -840,7 +956,7 @@ public static Bitmap addCornerBorder(final Bitmap src,
* @return the round bitmap with border
*/
public static Bitmap addCircleBorder(final Bitmap src,
- @IntRange(from = 1) final int borderSize,
+ @FloatRange(from = 1) final float borderSize,
@ColorInt final int color) {
return addBorder(src, borderSize, color, true, 0, false);
}
@@ -855,7 +971,7 @@ public static Bitmap addCircleBorder(final Bitmap src,
* @return the round bitmap with border
*/
public static Bitmap addCircleBorder(final Bitmap src,
- @IntRange(from = 1) final int borderSize,
+ @FloatRange(from = 1) final float borderSize,
@ColorInt final int color,
final boolean recycle) {
return addBorder(src, borderSize, color, true, 0, recycle);
@@ -873,11 +989,33 @@ public static Bitmap addCircleBorder(final Bitmap src,
* @return the bitmap with border
*/
private static Bitmap addBorder(final Bitmap src,
- @IntRange(from = 1) final int borderSize,
+ @FloatRange(from = 1) final float borderSize,
@ColorInt final int color,
final boolean isCircle,
final float cornerRadius,
final boolean recycle) {
+ float[] radii = {cornerRadius, cornerRadius, cornerRadius, cornerRadius,
+ cornerRadius, cornerRadius, cornerRadius, cornerRadius};
+ return addBorder(src, borderSize, color, isCircle, radii, recycle);
+ }
+
+ /**
+ * Return the bitmap with border.
+ *
+ * @param src The source of bitmap.
+ * @param borderSize The size of border.
+ * @param color The color of border.
+ * @param isCircle True to draw circle, false to draw corner.
+ * @param radii Array of 8 values, 4 pairs of [X,Y] radii
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the bitmap with border
+ */
+ private static Bitmap addBorder(final Bitmap src,
+ @FloatRange(from = 1) final float borderSize,
+ @ColorInt final int color,
+ final boolean isCircle,
+ final float[] radii,
+ final boolean recycle) {
if (isEmptyBitmap(src)) return null;
Bitmap ret = recycle ? src : src.copy(src.getConfig(), true);
int width = ret.getWidth();
@@ -891,10 +1029,12 @@ private static Bitmap addBorder(final Bitmap src,
float radius = Math.min(width, height) / 2f - borderSize / 2f;
canvas.drawCircle(width / 2f, height / 2f, radius, paint);
} else {
- int halfBorderSize = borderSize >> 1;
- RectF rectF = new RectF(halfBorderSize, halfBorderSize,
- width - halfBorderSize, height - halfBorderSize);
- canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint);
+ RectF rectF = new RectF(0, 0, width, height);
+ float halfBorderSize = borderSize / 2f;
+ rectF.inset(halfBorderSize, halfBorderSize);
+ Path path = new Path();
+ path.addRoundRect(rectF, radii, Path.Direction.CW);
+ canvas.drawPath(path, paint);
}
return ret;
}
@@ -1468,7 +1608,7 @@ public static Bitmap stackBlur(final Bitmap src, int radius, final boolean recyc
public static boolean save(final Bitmap src,
final String filePath,
final CompressFormat format) {
- return save(src, getFileByPath(filePath), format, false);
+ return save(src, filePath, format, 100, false);
}
/**
@@ -1480,7 +1620,7 @@ public static boolean save(final Bitmap src,
* @return {@code true}: success {@code false}: fail
*/
public static boolean save(final Bitmap src, final File file, final CompressFormat format) {
- return save(src, file, format, false);
+ return save(src, file, format, 100, false);
}
/**
@@ -1496,7 +1636,7 @@ public static boolean save(final Bitmap src,
final String filePath,
final CompressFormat format,
final boolean recycle) {
- return save(src, getFileByPath(filePath), format, recycle);
+ return save(src, filePath, format, 100, recycle);
}
/**
@@ -1512,12 +1652,99 @@ public static boolean save(final Bitmap src,
final File file,
final CompressFormat format,
final boolean recycle) {
- if (isEmptyBitmap(src) || !createFileByDeleteOldFile(file)) return false;
+ return save(src, file, format, 100, recycle);
+ }
+
+ /**
+ * Save the bitmap.
+ *
+ * @param src The source of bitmap.
+ * @param filePath The path of file.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean save(final Bitmap src,
+ final String filePath,
+ final CompressFormat format,
+ final int quality) {
+ return save(src, UtilsBridge.getFileByPath(filePath), format, quality, false);
+ }
+
+ /**
+ * Save the bitmap.
+ *
+ * @param src The source of bitmap.
+ * @param file The file.
+ * @param format The format of the image.
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean save(final Bitmap src,
+ final File file,
+ final CompressFormat format,
+ final int quality) {
+ return save(src, file, format, quality, false);
+ }
+
+ /**
+ * Save the bitmap.
+ *
+ * @param src The source of bitmap.
+ * @param filePath The path of file.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean save(final Bitmap src,
+ final String filePath,
+ final CompressFormat format,
+ final int quality,
+ final boolean recycle) {
+ return save(src, UtilsBridge.getFileByPath(filePath), format, quality, recycle);
+ }
+
+ /**
+ * Save the bitmap.
+ *
+ * @param src The source of bitmap.
+ * @param file The file.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return {@code true}: success {@code false}: fail
+ */
+ public static boolean save(final Bitmap src,
+ final File file,
+ final CompressFormat format,
+ final int quality,
+ final boolean recycle) {
+ if (isEmptyBitmap(src)) {
+ Log.e("ImageUtils", "bitmap is empty.");
+ return false;
+ }
+ if (src.isRecycled()) {
+ Log.e("ImageUtils", "bitmap is recycled.");
+ return false;
+ }
+ if (!UtilsBridge.createFileByDeleteOldFile(file)) {
+ Log.e("ImageUtils", "create or delete file <" + file + "> failed.");
+ return false;
+ }
OutputStream os = null;
boolean ret = false;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
- ret = src.compress(format, 100, os);
+ ret = src.compress(format, quality, os);
if (recycle && !src.isRecycled()) src.recycle();
} catch (IOException e) {
e.printStackTrace();
@@ -1533,6 +1760,184 @@ public static boolean save(final Bitmap src,
return ret;
}
+ /**
+ * @param src The source of bitmap.
+ * @param format The format of the image.
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final CompressFormat format) {
+ return save2Album(src, "", format, 100, false);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param format The format of the image.
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final CompressFormat format,
+ final boolean recycle) {
+ return save2Album(src, "", format, 100, recycle);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final CompressFormat format,
+ final int quality) {
+ return save2Album(src, "", format, quality, false);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final CompressFormat format,
+ final int quality,
+ final boolean recycle) {
+ return save2Album(src, "", format, quality, recycle);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param dirName The name of directory.
+ * @param format The format of the image.
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final String dirName,
+ final CompressFormat format) {
+ return save2Album(src, dirName, format, 100, false);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param dirName The name of directory.
+ * @param format The format of the image.
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final String dirName,
+ final CompressFormat format,
+ final boolean recycle) {
+ return save2Album(src, dirName, format, 100, recycle);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param dirName The name of directory.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final String dirName,
+ final CompressFormat format,
+ final int quality) {
+ return save2Album(src, dirName, format, quality, false);
+ }
+
+ /**
+ * @param src The source of bitmap.
+ * @param dirName The name of directory.
+ * @param format The format of the image.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality. Some
+ * formats, like PNG which is lossless, will ignore the
+ * quality setting
+ * @param recycle True to recycle the source of bitmap, false otherwise.
+ * @return the file if save success, otherwise return null.
+ */
+ @Nullable
+ public static File save2Album(final Bitmap src,
+ final String dirName,
+ final CompressFormat format,
+ final int quality,
+ final boolean recycle) {
+ String safeDirName = TextUtils.isEmpty(dirName) ? Utils.getApp().getPackageName() : dirName;
+ String suffix = CompressFormat.JPEG.equals(format) ? "JPG" : format.name();
+ String fileName = System.currentTimeMillis() + "_" + quality + "." + suffix;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ if (!UtilsBridge.isGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ Log.e("ImageUtils", "save to album need storage permission");
+ return null;
+ }
+ File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
+ File destFile = new File(picDir, safeDirName + "/" + fileName);
+ if (!save(src, destFile, format, quality, recycle)) {
+ return null;
+ }
+ UtilsBridge.notifySystemToScan(destFile);
+ return destFile;
+ } else {
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
+ contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/*");
+ Uri contentUri;
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ } else {
+ contentUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
+ }
+ contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/" + safeDirName);
+ contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
+ Uri uri = Utils.getApp().getContentResolver().insert(contentUri, contentValues);
+ if (uri == null) {
+ return null;
+ }
+ OutputStream os = null;
+ try {
+ os = Utils.getApp().getContentResolver().openOutputStream(uri);
+ src.compress(format, quality, os);
+
+ contentValues.clear();
+ contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
+ Utils.getApp().getContentResolver().update(uri, contentValues, null, null);
+
+ return UtilsBridge.uri2File(uri);
+ } catch (Exception e) {
+ Utils.getApp().getContentResolver().delete(uri, null, null);
+ e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ if (os != null) {
+ os.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
/**
* Return whether it is a image according to the file name.
*
@@ -1553,11 +1958,11 @@ public static boolean isImage(final File file) {
* @return {@code true}: yes {@code false}: no
*/
public static boolean isImage(final String filePath) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
try {
- Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
- return options.outWidth != -1 && options.outHeight != -1;
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(filePath, options);
+ return options.outWidth > 0 && options.outHeight > 0;
} catch (Exception e) {
return false;
}
@@ -1570,7 +1975,7 @@ public static boolean isImage(final String filePath) {
* @return the type of image
*/
public static ImageType getImageType(final String filePath) {
- return getImageType(getFileByPath(filePath));
+ return getImageType(UtilsBridge.getFileByPath(filePath));
}
/**
@@ -1614,7 +2019,7 @@ private static ImageType getImageType(final InputStream is) {
}
private static ImageType getImageType(final byte[] bytes) {
- String type = bytes2HexString(bytes).toUpperCase();
+ String type = UtilsBridge.bytes2HexString(bytes).toUpperCase();
if (type.contains("FFD8FF")) {
return ImageType.TYPE_JPG;
} else if (type.contains("89504E47")) {
@@ -1634,22 +2039,6 @@ private static ImageType getImageType(final byte[] bytes) {
}
}
- private static final char[] hexDigits =
- {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
- private static String bytes2HexString(final byte[] bytes) {
- if (bytes == null) return "";
- int len = bytes.length;
- if (len <= 0) return "";
- char[] ret = new char[len << 1];
- for (int i = 0, j = 0; i < len; i++) {
- ret[j++] = hexDigits[bytes[i] >> 4 & 0x0f];
- ret[j++] = hexDigits[bytes[i] & 0x0f];
- }
- return new String(ret);
- }
-
-
private static boolean isJPEG(final byte[] b) {
return b.length >= 2
&& (b[0] == (byte) 0xFF) && (b[1] == (byte) 0xD8);
@@ -1916,7 +2305,7 @@ public static Bitmap compressBySampleSize(final Bitmap src,
* @return the size of bitmap
*/
public static int[] getSize(String filePath) {
- return getSize(getFileByPath(filePath));
+ return getSize(UtilsBridge.getFileByPath(filePath));
}
/**
@@ -1942,8 +2331,8 @@ public static int[] getSize(File file) {
* @return the sample size
*/
public static int calculateInSampleSize(final BitmapFactory.Options options,
- final int maxWidth,
- final int maxHeight) {
+ final int maxWidth,
+ final int maxHeight) {
int height = options.outHeight;
int width = options.outWidth;
int inSampleSize = 1;
@@ -1955,62 +2344,6 @@ public static int calculateInSampleSize(final BitmapFactory.Options options,
return inSampleSize;
}
- ///////////////////////////////////////////////////////////////////////////
- // other utils methods
- ///////////////////////////////////////////////////////////////////////////
-
- private static File getFileByPath(final String filePath) {
- return isSpace(filePath) ? null : new File(filePath);
- }
-
- private static boolean createFileByDeleteOldFile(final File file) {
- if (file == null) return false;
- if (file.exists() && !file.delete()) return false;
- if (!createOrExistsDir(file.getParentFile())) return false;
- try {
- return file.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- private static boolean createOrExistsDir(final File file) {
- return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
- }
-
- private static boolean isSpace(final String s) {
- if (s == null) return true;
- for (int i = 0, len = s.length(); i < len; ++i) {
- if (!Character.isWhitespace(s.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- private static byte[] input2Byte(final InputStream is) {
- if (is == null) return null;
- try {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- byte[] b = new byte[1024];
- int len;
- while ((len = is.read(b, 0, 1024)) != -1) {
- os.write(b, 0, len);
- }
- return os.toByteArray();
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
public enum ImageType {
TYPE_JPG("jpg"),
diff --git a/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java b/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java
index fc86d34a05..a5009c3cba 100644
--- a/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java
+++ b/lib/utilcode/src/main/java/com/blankj/utilcode/util/IntentUtils.java
@@ -8,14 +8,17 @@
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
-import android.support.annotation.RequiresPermission;
-import android.support.v4.content.FileProvider;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresPermission;
+import androidx.core.content.FileProvider;
+
import static android.Manifest.permission.CALL_PHONE;
/**
@@ -54,7 +57,7 @@ public static boolean isIntentAvailable(final Intent intent) {
* @return the intent of install app
*/
public static Intent getInstallAppIntent(final String filePath) {
- return getInstallAppIntent(getFileByPath(filePath), false);
+ return getInstallAppIntent(UtilsBridge.getFileByPath(filePath));
}
/**
@@ -66,20 +69,15 @@ public static Intent getInstallAppIntent(final String filePath) {
* @return the intent of install app
*/
public static Intent getInstallAppIntent(final File file) {
- return getInstallAppIntent(file, false);
- }
-
- /**
- * Return the intent of install app.
- *
Target APIs greater than 25 must hold
- * {@code }
- *
- * @param filePath The path of file.
- * @param isNewTask True to add flag of new task, false otherwise.
- * @return the intent of install app
- */
- public static Intent getInstallAppIntent(final String filePath, final boolean isNewTask) {
- return getInstallAppIntent(getFileByPath(filePath), isNewTask);
+ if (!UtilsBridge.isFileExists(file)) return null;
+ Uri uri;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ uri = Uri.fromFile(file);
+ } else {
+ String authority = Utils.getApp().getPackageName() + ".utilcode.fileprovider";
+ uri = FileProvider.getUriForFile(Utils.getApp(), authority, file);
+ }
+ return getInstallAppIntent(uri);
}
/**
@@ -87,93 +85,68 @@ public static Intent getInstallAppIntent(final String filePath, final boolean is
*
Target APIs greater than 25 must hold
* {@code }
*
- * @param file The file.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param uri The uri.
* @return the intent of install app
*/
- public static Intent getInstallAppIntent(final File file, final boolean isNewTask) {
- if (file == null) return null;
+ public static Intent getInstallAppIntent(final Uri uri) {
+ if (uri == null) return null;
Intent intent = new Intent(Intent.ACTION_VIEW);
- Uri data;
String type = "application/vnd.android.package-archive";
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
- data = Uri.fromFile(file);
- } else {
+ intent.setDataAndType(uri, type);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- String authority = Utils.getApp().getPackageName() + ".utilcode.provider";
- data = FileProvider.getUriForFile(Utils.getApp(), authority, file);
}
- intent.setDataAndType(data, type);
- return getIntent(intent, isNewTask);
- }
-
- /**
- * Return the intent of uninstall app.
- *
- * @param packageName The name of the package.
- * @return the intent of uninstall app
- */
- public static Intent getUninstallAppIntent(final String packageName) {
- return getUninstallAppIntent(packageName, false);
+ return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
/**
* Return the intent of uninstall app.
+ *
Target APIs greater than 25 must hold
+ * Must hold {@code }
*
- * @param packageName The name of the package.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param pkgName The name of the package.
* @return the intent of uninstall app
*/
- public static Intent getUninstallAppIntent(final String packageName, final boolean isNewTask) {
+ public static Intent getUninstallAppIntent(final String pkgName) {
Intent intent = new Intent(Intent.ACTION_DELETE);
- intent.setData(Uri.parse("package:" + packageName));
- return getIntent(intent, isNewTask);
+ intent.setData(Uri.parse("package:" + pkgName));
+ return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
/**
* Return the intent of launch app.
*
- * @param packageName The name of the package.
+ * @param pkgName The name of the package.
* @return the intent of launch app
*/
- public static Intent getLaunchAppIntent(final String packageName) {
- return getLaunchAppIntent(packageName, false);
- }
-
- /**
- * Return the intent of launch app.
- *
- * @param packageName The name of the package.
- * @param isNewTask True to add flag of new task, false otherwise.
- * @return the intent of launch app
- */
- public static Intent getLaunchAppIntent(final String packageName, final boolean isNewTask) {
- Intent intent = Utils.getApp().getPackageManager().getLaunchIntentForPackage(packageName);
- if (intent == null) return null;
- return getIntent(intent, isNewTask);
+ public static Intent getLaunchAppIntent(final String pkgName) {
+ String launcherActivity = UtilsBridge.getLauncherActivity(pkgName);
+ if (UtilsBridge.isSpace(launcherActivity)) return null;
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setClassName(pkgName, launcherActivity);
+ return intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
/**
* Return the intent of launch app details settings.
*
- * @param packageName The name of the package.
+ * @param pkgName The name of the package.
* @return the intent of launch app details settings
*/
- public static Intent getLaunchAppDetailsSettingsIntent(final String packageName) {
- return getLaunchAppDetailsSettingsIntent(packageName, false);
+ public static Intent getLaunchAppDetailsSettingsIntent(final String pkgName) {
+ return getLaunchAppDetailsSettingsIntent(pkgName, false);
}
/**
* Return the intent of launch app details settings.
*
- * @param packageName The name of the package.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param pkgName The name of the package.
* @return the intent of launch app details settings
*/
- public static Intent getLaunchAppDetailsSettingsIntent(final String packageName,
- final boolean isNewTask) {
+ public static Intent getLaunchAppDetailsSettingsIntent(final String pkgName, final boolean isNewTask) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- intent.setData(Uri.parse("package:" + packageName));
+ intent.setData(Uri.parse("package:" + pkgName));
return getIntent(intent, isNewTask);
}
@@ -184,250 +157,223 @@ public static Intent getLaunchAppDetailsSettingsIntent(final String packageName,
* @return the intent of share text
*/
public static Intent getShareTextIntent(final String content) {
- return getShareTextIntent(content, false);
- }
-
- /**
- * Return the intent of share text.
- *
- * @param content The content.
- * @param isNewTask True to add flag of new task, false otherwise.
- * @return the intent of share text
- */
-
- public static Intent getShareTextIntent(final String content, final boolean isNewTask) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, content);
- return getIntent(intent, isNewTask);
+ intent = Intent.createChooser(intent, "");
+ return getIntent(intent, true);
}
/**
* Return the intent of share image.
*
- * @param content The content.
* @param imagePath The path of image.
* @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content, final String imagePath) {
- return getShareImageIntent(content, imagePath, false);
+ public static Intent getShareImageIntent(final String imagePath) {
+ return getShareTextImageIntent("", imagePath);
}
/**
* Return the intent of share image.
*
- * @param content The content.
- * @param imagePath The path of image.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param imageFile The file of image.
* @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content,
- final String imagePath,
- final boolean isNewTask) {
- if (imagePath == null || imagePath.length() == 0) return null;
- return getShareImageIntent(content, new File(imagePath), isNewTask);
+ public static Intent getShareImageIntent(final File imageFile) {
+ return getShareTextImageIntent("", imageFile);
}
/**
* Return the intent of share image.
*
- * @param content The content.
- * @param image The file of image.
+ * @param imageUri The uri of image.
* @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content, final File image) {
- return getShareImageIntent(content, image, false);
+ public static Intent getShareImageIntent(final Uri imageUri) {
+ return getShareTextImageIntent("", imageUri);
}
/**
* Return the intent of share image.
*
* @param content The content.
- * @param image The file of image.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param imagePath The path of image.
* @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content,
- final File image,
- final boolean isNewTask) {
- if (image == null || !image.isFile()) return null;
- return getShareImageIntent(content, file2Uri(image), isNewTask);
+ public static Intent getShareTextImageIntent(@Nullable final String content, final String imagePath) {
+ return getShareTextImageIntent(content, UtilsBridge.getFileByPath(imagePath));
}
/**
* Return the intent of share image.
*
- * @param content The content.
- * @param uri The uri of image.
+ * @param content The content.
+ * @param imageFile The file of image.
* @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content, final Uri uri) {
- return getShareImageIntent(content, uri, false);
+ public static Intent getShareTextImageIntent(@Nullable final String content, final File imageFile) {
+ return getShareTextImageIntent(content, UtilsBridge.file2Uri(imageFile));
}
/**
* Return the intent of share image.
*
- * @param content The content.
- * @param uri The uri of image.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param content The content.
+ * @param imageUri The uri of image.
* @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content,
- final Uri uri,
- final boolean isNewTask) {
+ public static Intent getShareTextImageIntent(@Nullable final String content, final Uri imageUri) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, content);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.putExtra(Intent.EXTRA_STREAM, imageUri);
intent.setType("image/*");
- return getIntent(intent, isNewTask);
+ intent = Intent.createChooser(intent, "");
+ return getIntent(intent, true);
}
/**
* Return the intent of share images.
*
- * @param content The content.
* @param imagePaths The paths of images.
* @return the intent of share images
*/
- public static Intent getShareImageIntent(final String content, final LinkedList imagePaths) {
- return getShareImageIntent(content, imagePaths, false);
+ public static Intent getShareImageIntent(final LinkedList imagePaths) {
+ return getShareTextImageIntent("", imagePaths);
}
/**
* Return the intent of share images.
*
- * @param content The content.
- * @param imagePaths The paths of images.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param images The files of images.
* @return the intent of share images
*/
- public static Intent getShareImageIntent(final String content,
- final LinkedList imagePaths,
- final boolean isNewTask) {
- if (imagePaths == null || imagePaths.isEmpty()) return null;
- List files = new ArrayList<>();
- for (String imagePath : imagePaths) {
- files.add(new File(imagePath));
- }
- return getShareImageIntent(content, files, isNewTask);
+ public static Intent getShareImageIntent(final List images) {
+ return getShareTextImageIntent("", images);
}
/**
* Return the intent of share images.
*
- * @param content The content.
- * @param images The files of images.
- * @return the intent of share images
+ * @param uris The uris of image.
+ * @return the intent of share image
*/
- public static Intent getShareImageIntent(final String content, final List images) {
- return getShareImageIntent(content, images, false);
+ public static Intent getShareImageIntent(final ArrayList uris) {
+ return getShareTextImageIntent("", uris);
}
/**
* Return the intent of share images.
*
- * @param content The content.
- * @param images The files of images.
- * @param isNewTask True to add flag of new task, false otherwise.
+ * @param content The content.
+ * @param imagePaths The paths of images.
* @return the intent of share images
*/
- public static Intent getShareImageIntent(final String content,
- final List images,
- final boolean isNewTask) {
- if (images == null || images.isEmpty()) return null;
- ArrayList uris = new ArrayList<>();
- for (File image : images) {
- if (!image.isFile()) continue;
- uris.add(file2Uri(image));
+ public static Intent getShareTextImageIntent(@Nullable final String content,
+ final LinkedList imagePaths) {
+ List files = new ArrayList<>();
+ if (imagePaths != null) {
+ for (String imagePath : imagePaths) {
+ File file = UtilsBridge.getFileByPath(imagePath);
+ if (file != null) {
+ files.add(file);
+ }
+ }
}
- return getShareImageIntent(content, uris, isNewTask);
+ return getShareTextImageIntent(content, files);
}
/**
* Return the intent of share images.
*
* @param content The content.
- * @param uris The uris of images.
+ * @param images The files of images.
* @return the intent of share images
*/
- public static Intent getShareImageIntent(final String content, final ArrayList uris) {
- return getShareImageIntent(content, uris, false);
+ public static Intent getShareTextImageIntent(@Nullable final String content, final List images) {
+ ArrayList