2.17 支持原生相机 支持压缩+水印时间,默认压缩不默认添加时间;支持霍尼韦尔eda52服务扫描
This commit is contained in:
@ -11,7 +11,7 @@ android {
|
|||||||
minSdk 28
|
minSdk 28
|
||||||
targetSdk 28
|
targetSdk 28
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "2.16"
|
versionName "2.17"
|
||||||
|
|
||||||
// 1.0 IDATA广播模式处理
|
// 1.0 IDATA广播模式处理
|
||||||
// 1.1 霍尼韦尔的监听修改(扫描网站二维码跳出程序,监听失效,调整)、斑马PDA广播模式设置
|
// 1.1 霍尼韦尔的监听修改(扫描网站二维码跳出程序,监听失效,调整)、斑马PDA广播模式设置
|
||||||
@ -52,6 +52,7 @@ android {
|
|||||||
// 2.14 适配 AIFUU 陈安良:陆军特色中心医院
|
// 2.14 适配 AIFUU 陈安良:陆军特色中心医院
|
||||||
// 2.15 添加文件选择和相机拍照功能
|
// 2.15 添加文件选择和相机拍照功能
|
||||||
// 2.16 暴露了一个直接调用相机的方法,非http input调用会出现默认的弹出窗口进行选择(相机、文件)
|
// 2.16 暴露了一个直接调用相机的方法,非http input调用会出现默认的弹出窗口进行选择(相机、文件)
|
||||||
|
// 2.17 支持原生相机,默认压缩;支持霍尼韦尔eda52服务扫描
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters 'armeabi-v7a'
|
abiFilters 'armeabi-v7a'
|
||||||
|
|||||||
@ -167,6 +167,7 @@ public class MainActivity extends AppCompatActivity implements ResultListener{
|
|||||||
if (
|
if (
|
||||||
"eda50p".equals(Build.MODEL.toLowerCase())
|
"eda50p".equals(Build.MODEL.toLowerCase())
|
||||||
|| "eda51".equals(Build.MODEL.toLowerCase())
|
|| "eda51".equals(Build.MODEL.toLowerCase())
|
||||||
|
|| "eda52".equals(Build.MODEL.toLowerCase())
|
||||||
|| "tc26".equals(Build.MODEL.toLowerCase())
|
|| "tc26".equals(Build.MODEL.toLowerCase())
|
||||||
) {
|
) {
|
||||||
// 走服务模式
|
// 走服务模式
|
||||||
|
|||||||
@ -98,14 +98,7 @@ public class HoneywellAdapter implements Adapter {
|
|||||||
|
|
||||||
public void openContinueScan(){
|
public void openContinueScan(){
|
||||||
|
|
||||||
if("eda50p".equals(Build.MODEL.toLowerCase())){ // 扫描正常
|
if("eda50p".equals(Build.MODEL.toLowerCase()) || "eda51".equals(Build.MODEL.toLowerCase()) || "eda52".equals(Build.MODEL.toLowerCase())){ // 扫描正常
|
||||||
intent = new Intent(context, ScanServiceEDA50P.class);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
context.getApplicationContext().startForegroundService(intent);
|
|
||||||
}else {
|
|
||||||
context.getApplicationContext().startService(intent);
|
|
||||||
}
|
|
||||||
}else if("eda51".equals(Build.MODEL.toLowerCase())){ // 扫描正常
|
|
||||||
intent = new Intent(context, ScanServiceEDA50P.class);
|
intent = new Intent(context, ScanServiceEDA50P.class);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
context.getApplicationContext().startForegroundService(intent);
|
context.getApplicationContext().startForegroundService(intent);
|
||||||
|
|||||||
@ -9,6 +9,12 @@ import android.content.pm.ActivityInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.media.ExifInterface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
@ -34,11 +40,11 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -64,12 +70,18 @@ public class LocalAddressUtil {
|
|||||||
private static final String DEFAULT_CAMERA_CALLBACK = "onNativeCameraResult";
|
private static final String DEFAULT_CAMERA_CALLBACK = "onNativeCameraResult";
|
||||||
|
|
||||||
// Base64 settings for camera callback
|
// Base64 settings for camera callback
|
||||||
private static final int CAMERA_IMAGE_MAX_DIMENSION = 1280;
|
private static final int CAMERA_IMAGE_DECODE_MAX_DIMENSION = 3200;
|
||||||
private static final int CAMERA_IMAGE_JPEG_QUALITY = 80;
|
private static final int CAMERA_OUTPUT_JPEG_QUALITY = 90;
|
||||||
private static final String CAMERA_DATA_URL_PREFIX = "data:image/jpeg;base64,";
|
private static final int CAMERA_OUTPUT_JPEG_MIN_QUALITY = 55;
|
||||||
|
private static final int CAMERA_OUTPUT_BASE64_MAX_BYTES = 500 * 1024;
|
||||||
|
private static final int CAMERA_OUTPUT_IMAGE_MAX_BYTES = CAMERA_OUTPUT_BASE64_MAX_BYTES / 4 * 3;
|
||||||
|
private static final String CAMERA_RAW_DATA_URL_PREFIX = "data:image/jpeg;base64,";
|
||||||
|
private static final String CAMERA_WATERMARK_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
private Uri nativeCameraPhotoUri;
|
private Uri nativeCameraPhotoUri;
|
||||||
private String pendingCameraCallback = null;
|
private String pendingCameraCallback = null;
|
||||||
|
private boolean pendingCameraCompress = true;
|
||||||
|
private boolean pendingCameraWatermark = false;
|
||||||
|
|
||||||
public LocalAddressUtil(Context context, Activity activity, View view) {
|
public LocalAddressUtil(Context context, Activity activity, View view) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -84,7 +96,7 @@ public class LocalAddressUtil {
|
|||||||
@SuppressLint("JavascriptInterface")
|
@SuppressLint("JavascriptInterface")
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void openNativeCamera() {
|
public void openNativeCamera() {
|
||||||
openNativeCamera(DEFAULT_CAMERA_CALLBACK);
|
openNativeCamera(DEFAULT_CAMERA_CALLBACK, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,9 +106,23 @@ public class LocalAddressUtil {
|
|||||||
@SuppressLint("JavascriptInterface")
|
@SuppressLint("JavascriptInterface")
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void openNativeCamera(String callback) {
|
public void openNativeCamera(String callback) {
|
||||||
|
openNativeCamera(callback, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接调用原生相机(自定义回调函数名:window[callback](base64OrDataUrl, error))
|
||||||
|
* @param callback JS 回调函数名(不需要传 window. 前缀)
|
||||||
|
* @param needCompress 是否压缩,默认压缩到约 500KB base64
|
||||||
|
* @param addWatermark 是否添加拍照时间水印
|
||||||
|
*/
|
||||||
|
@SuppressLint("JavascriptInterface")
|
||||||
|
@JavascriptInterface
|
||||||
|
public void openNativeCamera(String callback, boolean needCompress, boolean addWatermark) {
|
||||||
this.pendingCameraCallback = (callback == null || callback.trim().isEmpty())
|
this.pendingCameraCallback = (callback == null || callback.trim().isEmpty())
|
||||||
? DEFAULT_CAMERA_CALLBACK
|
? DEFAULT_CAMERA_CALLBACK
|
||||||
: callback.trim();
|
: callback.trim();
|
||||||
|
this.pendingCameraCompress = needCompress;
|
||||||
|
this.pendingCameraWatermark = addWatermark;
|
||||||
|
|
||||||
if (!checkCameraPermission()) {
|
if (!checkCameraPermission()) {
|
||||||
ActivityCompat.requestPermissions(activity,
|
ActivityCompat.requestPermissions(activity,
|
||||||
@ -127,7 +153,7 @@ public class LocalAddressUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
String dataUrl = buildCameraPhotoDataUrl(nativeCameraPhotoUri);
|
String dataUrl = buildCameraPhotoDataUrl(nativeCameraPhotoUri, pendingCameraCompress, pendingCameraWatermark);
|
||||||
if (dataUrl == null || dataUrl.trim().isEmpty()) {
|
if (dataUrl == null || dataUrl.trim().isEmpty()) {
|
||||||
dispatchCameraResultToJs(null, "encode_failed");
|
dispatchCameraResultToJs(null, "encode_failed");
|
||||||
} else {
|
} else {
|
||||||
@ -137,6 +163,8 @@ public class LocalAddressUtil {
|
|||||||
dispatchCameraResultToJs(null, "cancelled");
|
dispatchCameraResultToJs(null, "cancelled");
|
||||||
}
|
}
|
||||||
nativeCameraPhotoUri = null;
|
nativeCameraPhotoUri = null;
|
||||||
|
pendingCameraCompress = true;
|
||||||
|
pendingCameraWatermark = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +178,7 @@ public class LocalAddressUtil {
|
|||||||
boolean granted = grantResults != null && grantResults.length > 0
|
boolean granted = grantResults != null && grantResults.length > 0
|
||||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
||||||
if (granted) {
|
if (granted) {
|
||||||
openNativeCamera(pendingCameraCallback);
|
openNativeCamera(pendingCameraCallback, pendingCameraCompress, pendingCameraWatermark);
|
||||||
} else {
|
} else {
|
||||||
dispatchCameraResultToJs(null, "permission_denied");
|
dispatchCameraResultToJs(null, "permission_denied");
|
||||||
}
|
}
|
||||||
@ -201,10 +229,39 @@ public class LocalAddressUtil {
|
|||||||
/**
|
/**
|
||||||
* 将拍照结果转为 dataUrl(base64)
|
* 将拍照结果转为 dataUrl(base64)
|
||||||
*/
|
*/
|
||||||
private String buildCameraPhotoDataUrl(Uri uri) {
|
private String buildCameraPhotoDataUrl(Uri uri, boolean needCompress, boolean addWatermark) {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
byte[] rawBytes;
|
||||||
|
try {
|
||||||
|
rawBytes = readBytesFromUri(uri);
|
||||||
|
if (rawBytes == null || rawBytes.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "读取原图失败", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addWatermark && (!needCompress || rawBytes.length <= CAMERA_OUTPUT_IMAGE_MAX_BYTES)) {
|
||||||
|
String base64 = Base64.encodeToString(rawBytes, Base64.NO_WRAP);
|
||||||
|
String dataUrl = CAMERA_RAW_DATA_URL_PREFIX + base64;
|
||||||
|
Log.i(TAG, "camera_base64_size rawBytes=" + rawBytes.length
|
||||||
|
+ " rawKb=" + String.format(Locale.getDefault(), "%.2f", rawBytes.length / 1024f)
|
||||||
|
+ " resultBytes=" + rawBytes.length
|
||||||
|
+ " resultKb=" + String.format(Locale.getDefault(), "%.2f", rawBytes.length / 1024f)
|
||||||
|
+ " base64Chars=" + base64.length()
|
||||||
|
+ " base64Kb=" + String.format(Locale.getDefault(), "%.2f", base64.length() / 1024f)
|
||||||
|
+ " dataUrlChars=" + dataUrl.length()
|
||||||
|
+ " needCompress=" + needCompress
|
||||||
|
+ " addWatermark=" + addWatermark
|
||||||
|
+ " outputWidth=raw"
|
||||||
|
+ " outputHeight=raw"
|
||||||
|
+ " outputFormat=jpeg_raw");
|
||||||
|
return dataUrl;
|
||||||
|
}
|
||||||
|
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
try {
|
try {
|
||||||
inputStream = context.getContentResolver().openInputStream(uri);
|
inputStream = context.getContentResolver().openInputStream(uri);
|
||||||
@ -213,31 +270,139 @@ public class LocalAddressUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
options.inJustDecodeBounds = true;
|
if (needCompress) {
|
||||||
BitmapFactory.decodeStream(inputStream, null, options);
|
options.inJustDecodeBounds = true;
|
||||||
int srcW = options.outWidth;
|
BitmapFactory.decodeStream(inputStream, null, options);
|
||||||
int srcH = options.outHeight;
|
safeClose(inputStream);
|
||||||
|
inputStream = context.getContentResolver().openInputStream(uri);
|
||||||
safeClose(inputStream);
|
if (inputStream == null) {
|
||||||
inputStream = context.getContentResolver().openInputStream(uri);
|
return null;
|
||||||
if (inputStream == null) {
|
}
|
||||||
return null;
|
options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, CAMERA_IMAGE_DECODE_MAX_DIMENSION);
|
||||||
|
options.inJustDecodeBounds = false;
|
||||||
}
|
}
|
||||||
|
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||||
options.inSampleSize = calculateInSampleSize(srcW, srcH, CAMERA_IMAGE_MAX_DIMENSION);
|
|
||||||
options.inJustDecodeBounds = false;
|
|
||||||
|
|
||||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rotateDegree = readImageRotateDegree(uri);
|
||||||
|
if (rotateDegree != 0) {
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postRotate(rotateDegree);
|
||||||
|
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||||
|
if (rotatedBitmap != bitmap) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = rotatedBitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addWatermark) {
|
||||||
|
Bitmap.Config config = bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
|
||||||
|
if (!bitmap.isMutable()) {
|
||||||
|
Bitmap watermarkBitmap = bitmap.copy(config, true);
|
||||||
|
if (watermarkBitmap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (watermarkBitmap != bitmap) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = watermarkBitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
String watermark = new SimpleDateFormat(CAMERA_WATERMARK_TIME_PATTERN, Locale.getDefault()).format(new Date());
|
||||||
|
float textSize = Math.max(28f, bitmap.getWidth() / 16f);
|
||||||
|
float padding = Math.max(18f, textSize * 0.45f);
|
||||||
|
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
textPaint.setColor(Color.WHITE);
|
||||||
|
textPaint.setTextSize(textSize);
|
||||||
|
textPaint.setFakeBoldText(true);
|
||||||
|
textPaint.setShadowLayer(4f, 0f, 1f, 0x66000000);
|
||||||
|
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
|
||||||
|
Rect textBounds = new Rect();
|
||||||
|
textPaint.getTextBounds(watermark, 0, watermark.length(), textBounds);
|
||||||
|
float left = padding;
|
||||||
|
float bottom = bitmap.getHeight() - padding;
|
||||||
|
float top = bottom - (fontMetrics.descent - fontMetrics.ascent) - padding * 1.6f;
|
||||||
|
float right = left + textBounds.width() + padding * 2f;
|
||||||
|
Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
bgPaint.setColor(0xB3000000);
|
||||||
|
canvas.drawRoundRect(left, top, right, bottom, padding, padding, bgPaint);
|
||||||
|
Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
borderPaint.setColor(0x66FFFFFF);
|
||||||
|
borderPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
borderPaint.setStrokeWidth(Math.max(2f, textSize / 14f));
|
||||||
|
canvas.drawRoundRect(left, top, right, bottom, padding, padding, borderPaint);
|
||||||
|
float textY = bottom - padding - fontMetrics.descent;
|
||||||
|
canvas.drawText(watermark, left + padding, textY, textPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes;
|
||||||
|
int quality = CAMERA_OUTPUT_JPEG_QUALITY;
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, CAMERA_IMAGE_JPEG_QUALITY, baos);
|
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
|
||||||
byte[] bytes = baos.toByteArray();
|
bytes = baos.toByteArray();
|
||||||
|
int outputWidth = bitmap.getWidth();
|
||||||
|
int outputHeight = bitmap.getHeight();
|
||||||
|
|
||||||
|
if (needCompress && bytes.length > CAMERA_OUTPUT_IMAGE_MAX_BYTES) {
|
||||||
|
int guard = 0;
|
||||||
|
while (bytes.length > CAMERA_OUTPUT_IMAGE_MAX_BYTES && guard < 12) {
|
||||||
|
guard++;
|
||||||
|
while (bytes.length > CAMERA_OUTPUT_IMAGE_MAX_BYTES && quality > CAMERA_OUTPUT_JPEG_MIN_QUALITY) {
|
||||||
|
quality = Math.max(CAMERA_OUTPUT_JPEG_MIN_QUALITY, quality - 5);
|
||||||
|
baos.reset();
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
|
||||||
|
bytes = baos.toByteArray();
|
||||||
|
}
|
||||||
|
if (bytes.length <= CAMERA_OUTPUT_IMAGE_MAX_BYTES) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextWidth = Math.max(1, Math.round(bitmap.getWidth() * 0.85f));
|
||||||
|
int nextHeight = Math.max(1, Math.round(bitmap.getHeight() * 0.85f));
|
||||||
|
if (nextWidth == bitmap.getWidth() && nextHeight == bitmap.getHeight()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, nextWidth, nextHeight, true);
|
||||||
|
if (scaledBitmap != bitmap) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = scaledBitmap;
|
||||||
|
}
|
||||||
|
outputWidth = bitmap.getWidth();
|
||||||
|
outputHeight = bitmap.getHeight();
|
||||||
|
quality = CAMERA_OUTPUT_JPEG_QUALITY;
|
||||||
|
baos.reset();
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
|
||||||
|
bytes = baos.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap.recycle();
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
String base64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
|
String base64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
|
||||||
return CAMERA_DATA_URL_PREFIX + base64;
|
String dataUrl = CAMERA_RAW_DATA_URL_PREFIX + base64;
|
||||||
|
Log.i(TAG, "camera_base64_size rawBytes=" + rawBytes.length
|
||||||
|
+ " rawKb=" + String.format(Locale.getDefault(), "%.2f", rawBytes.length / 1024f)
|
||||||
|
+ " resultBytes=" + bytes.length
|
||||||
|
+ " resultKb=" + String.format(Locale.getDefault(), "%.2f", bytes.length / 1024f)
|
||||||
|
+ " base64Chars=" + base64.length()
|
||||||
|
+ " base64Kb=" + String.format(Locale.getDefault(), "%.2f", base64.length() / 1024f)
|
||||||
|
+ " dataUrlChars=" + dataUrl.length()
|
||||||
|
+ " needCompress=" + needCompress
|
||||||
|
+ " addWatermark=" + addWatermark
|
||||||
|
+ " outputWidth=" + outputWidth
|
||||||
|
+ " outputHeight=" + outputHeight
|
||||||
|
+ " jpegQuality=" + quality
|
||||||
|
+ " targetBytes=" + (needCompress ? CAMERA_OUTPUT_IMAGE_MAX_BYTES : -1)
|
||||||
|
+ " outputFormat=jpeg");
|
||||||
|
return dataUrl;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "图片转base64失败", e);
|
Log.e(TAG, "图片转base64失败", e);
|
||||||
return null;
|
return null;
|
||||||
@ -246,14 +411,56 @@ public class LocalAddressUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] readBytesFromUri(Uri uri) throws IOException {
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = context.getContentResolver().openInputStream(uri);
|
||||||
|
if (inputStream == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int len;
|
||||||
|
while ((len = inputStream.read(buffer)) != -1) {
|
||||||
|
baos.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
return baos.toByteArray();
|
||||||
|
} finally {
|
||||||
|
safeClose(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readImageRotateDegree(Uri uri) {
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = context.getContentResolver().openInputStream(uri);
|
||||||
|
if (inputStream == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ExifInterface exifInterface = new ExifInterface(inputStream);
|
||||||
|
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||||
|
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
|
||||||
|
return 90;
|
||||||
|
}
|
||||||
|
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
|
||||||
|
return 180;
|
||||||
|
}
|
||||||
|
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
|
||||||
|
return 270;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "读取图片方向失败", e);
|
||||||
|
} finally {
|
||||||
|
safeClose(inputStream);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private int calculateInSampleSize(int srcW, int srcH, int maxDim) {
|
private int calculateInSampleSize(int srcW, int srcH, int maxDim) {
|
||||||
if (srcW <= 0 || srcH <= 0) {
|
if (srcW <= 0 || srcH <= 0 || maxDim <= 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int maxSrc = Math.max(srcW, srcH);
|
int maxSrc = Math.max(srcW, srcH);
|
||||||
if (maxSrc <= maxDim) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int inSampleSize = 1;
|
int inSampleSize = 1;
|
||||||
while (maxSrc / inSampleSize > maxDim) {
|
while (maxSrc / inSampleSize > maxDim) {
|
||||||
inSampleSize *= 2;
|
inSampleSize *= 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user