From e707012aece3103b794c1988698bdd15b31aa019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?whalensun=28=E5=AD=99=E4=BC=9F=29?= <532125505@qq.com> Date: Mon, 21 Feb 2022 13:51:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E8=A7=84=E4=BF=AE=E5=A4=8D-=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E4=BA=8C=E7=BB=B4=E7=A0=81=E5=A4=84=E7=9A=84=E4=BB=8E?= =?UTF-8?q?=E7=9B=B8=E5=86=8C=E9=80=89=E6=8B=A9=E6=9D=83=E9=99=90=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86=EF=BC=8C=E4=BB=A5=E5=8F=8A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=BE=E5=A4=87=E9=A1=B5=E9=9D=A2=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=8F=90=E7=A4=BA=E6=B6=88=E5=A4=B1=E7=9A=84bug?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic6787a0ae590a2e762d6f5cfd8c7f10d504af40e --- app/src/main/AndroidManifest.xml | 1 + .../activity/DeviceCategoryActivity.kt | 3 +- .../link/kitlink/activity/MainActivity.kt | 1 - .../kitlink/activity/ScannerActivity.java | 367 ++++++++++++++++++ .../link/kitlink/util/BeepManager.java | 112 ++++++ app/src/main/res/values-en-rUS/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 8 files changed, 484 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/ScannerActivity.java create mode 100644 app/src/main/java/com/tencent/iot/explorer/link/kitlink/util/BeepManager.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 827b86f9a..c43c6a2a5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -125,6 +125,7 @@ + diff --git a/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/DeviceCategoryActivity.kt b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/DeviceCategoryActivity.kt index 4c017d110..c983ea2a3 100644 --- a/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/DeviceCategoryActivity.kt +++ b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/DeviceCategoryActivity.kt @@ -22,7 +22,6 @@ import androidx.recyclerview.widget.GridLayoutManager import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONObject import com.example.qrcode.Constant -import com.example.qrcode.ScannerActivity import com.tencent.iot.explorer.link.App import com.tencent.iot.explorer.link.R import com.tencent.iot.explorer.link.T @@ -532,7 +531,7 @@ class DeviceCategoryActivity : PActivity(), MyCallback, CRecyclerView.RecyclerI return } requestPermission(blueToothPermissions) - permissionDialog = PermissionDialog(App.activity, R.mipmap.permission_location ,getString(R.string.permission_location_lips), getString(R.string.permission_location_ssid_ble)) + permissionDialog = PermissionDialog(this@DeviceCategoryActivity, R.mipmap.permission_location ,getString(R.string.permission_location_lips), getString(R.string.permission_location_ssid_ble)) permissionDialog!!.show() // 记录请求camera权限的时间 diff --git a/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/MainActivity.kt b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/MainActivity.kt index 9a56fb632..2e7c2fc75 100644 --- a/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/MainActivity.kt +++ b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/MainActivity.kt @@ -16,7 +16,6 @@ import androidx.fragment.app.Fragment import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONObject import com.example.qrcode.Constant -import com.example.qrcode.ScannerActivity import com.tencent.android.tpush.XGIOperateCallback import com.tencent.android.tpush.XGPushConfig import com.tencent.android.tpush.XGPushManager diff --git a/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/ScannerActivity.java b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/ScannerActivity.java new file mode 100644 index 000000000..a93656dd0 --- /dev/null +++ b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/activity/ScannerActivity.java @@ -0,0 +1,367 @@ +package com.tencent.iot.explorer.link.kitlink.activity; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.example.qrcode.Constant; +import com.example.qrcode.camera.CameraManager; +import com.example.qrcode.decode.InactivityTimer; +import com.example.qrcode.decode.ScannerHandler; +import com.example.qrcode.utils.CommonUtils; +import com.example.qrcode.utils.DecodeUtils; +import com.example.qrcode.utils.UriUtils; +import com.example.qrcode.view.ScannerView; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.Result; +import com.tencent.iot.explorer.link.R; +import com.tencent.iot.explorer.link.T; +import com.tencent.iot.explorer.link.core.utils.Utils; +import com.tencent.iot.explorer.link.customview.dialog.PermissionDialog; +import com.tencent.iot.explorer.link.kitlink.consts.CommonField; +import com.tencent.iot.explorer.link.kitlink.util.BeepManager; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Set; + + +/** + * Created by yangyu on 17/10/18. + */ + +public class ScannerActivity extends com.example.qrcode.ScannerActivity implements SurfaceHolder.Callback { + private static final String TAG = "ScannerActivity"; + + public static final String BARCODE_FORMAT = "support_barcode_format"; + public final int PERMISSION_REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 0X11; + public final int REQUEST_CODE_GET_PIC_URI = 0X12; + private final int MESSAGE_DECODE_FROM_BITMAP = 0; + + private Toolbar mToolBar; + private ScannerView mScannerView; + private SurfaceView mSurfaceView; + + private InactivityTimer mInactivityTimer; + private BeepManager beepManager; + + private CameraManager cameraManager; + private ScannerHandler handler; + private Collection decodeFormats; + + private int mScanFocusWidth; + private int mScanFocusHeight; + private int mScanFocusTopPadding; + + private boolean isEnableScanFromPicture; + private boolean hasSurface; + private MyHandler mHandler; + + private PermissionDialog permissionDialog = null; + + private static class MyHandler extends Handler { + private WeakReference activity; + + MyHandler(ScannerActivity mainActivityWeakReference) { + activity = new WeakReference(mainActivityWeakReference); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + ScannerActivity activity = this.activity.get(); + if (activity != null) { + if (msg.what == activity.MESSAGE_DECODE_FROM_BITMAP) { + Bitmap bm = (Bitmap) msg.obj; + DecodeUtils.DecodeAsyncTask decodeAsyncTask = new DecodeUtils.DecodeAsyncTask(activity); + decodeAsyncTask.execute(bm); + } + } + } + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(com.example.qrcode.R.layout.layout_activity_scanner); + initView(); + hasSurface = false; + Intent intent = getIntent(); + if (intent != null) { + mScanFocusWidth = intent.getIntExtra(Constant.EXTRA_SCANNER_FRAME_WIDTH, -1); + mScanFocusHeight = intent.getIntExtra(Constant.EXTRA_SCANNER_FRAME_HEIGHT, -1); + mScanFocusTopPadding = intent.getIntExtra(Constant.EXTRA_SCANNER_FRAME_TOP_PADDING, -1); + isEnableScanFromPicture = intent.getBooleanExtra(Constant.EXTRA_IS_ENABLE_SCAN_FROM_PIC, false); + Bundle b = intent.getExtras(); + if (b != null) { + HashMap formats = (HashMap) b.getSerializable(Constant.EXTRA_SCAN_CODE_TYPE); + if (formats != null) { + decodeFormats = formats.get(BARCODE_FORMAT); + } else { + decodeFormats = EnumSet.of(BarcodeFormat.QR_CODE + , BarcodeFormat.CODE_128); + } + } else { + decodeFormats = EnumSet.of(BarcodeFormat.QR_CODE + , BarcodeFormat.CODE_128); + } + + } + Log.e(TAG, "onCreate:decodeFormats :" + decodeFormats.size() + "--" + decodeFormats.toString()); + mInactivityTimer = new InactivityTimer(this); + beepManager = new BeepManager(this); + mHandler = new MyHandler(this); + } + + @Override + protected void onResume() { + super.onResume(); + cameraManager = new CameraManager(this); + cameraManager.setManualFramingRect(mScanFocusWidth, mScanFocusHeight, mScanFocusTopPadding); + mScannerView.setCameraManager(cameraManager); + SurfaceHolder holder = mSurfaceView.getHolder(); + + if (hasSurface) { + initCamera(holder); + } else { + holder.addCallback(this); + } + mInactivityTimer.onResume(); + beepManager.updatePrefs(); + } + + @Override + protected void onPause() { + super.onPause(); + if (handler != null) { + handler.quitSynchronously(); + handler = null; + } + cameraManager.closeDriver(); + mInactivityTimer.onPause(); + beepManager.close(); + } + + @Override + protected void onDestroy() { + cameraManager.clearFramingRect(); + mInactivityTimer.shutdown(); + super.onDestroy(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + //关闭灯光 + cameraManager.setTorch(false); + return true; + case KeyEvent.KEYCODE_VOLUME_UP: + //开启闪光灯 + cameraManager.setTorch(true); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + if (isEnableScanFromPicture) { + getMenuInflater().inflate(com.example.qrcode.R.menu.menu_scan, menu); + return true; + } else { + return super.onCreateOptionsMenu(menu); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int itemId = item.getItemId(); + if (itemId == com.example.qrcode.R.id.scan_from_picture) { + //先申请权限 + int checked = ContextCompat.checkSelfPermission(ScannerActivity.this + , Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (checked == PackageManager.PERMISSION_GRANTED) { + goPicture(); + } else { + // 查看请求album权限的时间是否大于48小时 + String albumJsonString = Utils.INSTANCE.getStringValueFromXml(this, CommonField.PERMISSION_ALBUM, CommonField.PERMISSION_ALBUM); + long lasttime = 0L; + if (albumJsonString != null) { + JSONObject albumJson = JSON.parseObject(albumJsonString); + lasttime = albumJson.getLong(CommonField.PERMISSION_ALBUM); + } + if (albumJsonString != null && lasttime > 0 && System.currentTimeMillis() / 1000 - lasttime < 48 * 60 * 60) { + T.show(getString(R.string.permission_of_album_refuse)); + return false; + } + if (permissionDialog == null) { + permissionDialog = new PermissionDialog(this, R.mipmap.permission_album ,getString(R.string.permission_album_lips), getString(R.string.permission_album_qrcode)); + permissionDialog.show(); + } + ActivityCompat.requestPermissions(ScannerActivity.this + , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE_WRITE_EXTERNAL_STORAGE); + + // 记录请求album权限的时间 + JSONObject json = new JSONObject(); + json.put(CommonField.PERMISSION_ALBUM, System.currentTimeMillis() / 1000); + Utils.INSTANCE.setXmlStringValue(this, CommonField.PERMISSION_ALBUM, CommonField.PERMISSION_ALBUM, json.toJSONString()); + + } + } + return true; + } + + private void goPicture() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + startActivityForResult(intent, REQUEST_CODE_GET_PIC_URI); + } + + private void initView() { + mToolBar = (Toolbar) findViewById(com.example.qrcode.R.id.tool_bar); + mToolBar.setTitle("二维码/条形码"); + mToolBar.setTitleTextColor(Color.WHITE); + mToolBar.setBackgroundColor(Color.DKGRAY); + setSupportActionBar(mToolBar); + mToolBar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + mSurfaceView = (SurfaceView) findViewById(com.example.qrcode.R.id.surface); + mScannerView = (ScannerView) findViewById(com.example.qrcode.R.id.scan_view); + } + + + private void initCamera(SurfaceHolder surfaceHolder) { + if (surfaceHolder == null) { + throw new IllegalStateException("No SurfaceHolder provided"); + } + if (cameraManager.isOpen()) { + Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?"); + return; + } + try { + cameraManager.openDriver(surfaceHolder); + if (handler == null) { + handler = new ScannerHandler(this, decodeFormats, "utf-8", cameraManager); + } + } catch (IOException ioe) { + Log.w(TAG, ioe); + } catch (RuntimeException e) { + Log.w(TAG, "Unexpected error initializing camera", e); + } + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + if (holder == null) { + Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!"); + } + if (!hasSurface) { + hasSurface = true; + initCamera(holder); + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + hasSurface = false; + } + + //在这里处理扫码结果 + public void handDecode(final Result result) { + mInactivityTimer.onActivity(); + beepManager.playBeepSoundAndVibrate(); +// AlertDialog.Builder mScannerDialogBuilder = new AlertDialog.Builder(this); +// mScannerDialogBuilder.setMessage("codeType:" + result.getBarcodeFormat() + "-----content:" + result.getText()); +// mScannerDialogBuilder.setCancelable(false); +// mScannerDialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialog, int which) { +// dialog.dismiss(); +// ScannerActivity.this.finish(); +// } +// }); +// mScannerDialogBuilder.create().show(); + Intent data = new Intent(); + BarcodeFormat format = result.getBarcodeFormat(); + String type = format.toString(); + data.putExtra(Constant.EXTRA_RESULT_CODE_TYPE, type); + data.putExtra(Constant.EXTRA_RESULT_CONTENT, result.getText()); + setResult(RESULT_OK, data); + finish(); + } + + public CameraManager getCameraManager() { + return cameraManager; + } + + public Handler getHandler() { + return handler; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + switch (requestCode) { + case REQUEST_CODE_GET_PIC_URI: + Uri uri = data.getData(); + String imagePath = UriUtils.getPicturePathFromUri(ScannerActivity.this, uri); + //对获取到的二维码照片进行压缩 + Bitmap bitmap = CommonUtils.compressPicture(imagePath); + Message message = mHandler.obtainMessage(MESSAGE_DECODE_FROM_BITMAP, bitmap); + mHandler.sendMessage(message); + Log.e(TAG, "onActivityResult: uri:" + uri.toString()); + break; + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + permissionDialog.dismiss(); + permissionDialog = null; + if (requestCode == PERMISSION_REQUEST_CODE_WRITE_EXTERNAL_STORAGE) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + goPicture(); + return; + } + } + } + + +} diff --git a/app/src/main/java/com/tencent/iot/explorer/link/kitlink/util/BeepManager.java b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/util/BeepManager.java new file mode 100644 index 000000000..5b4994842 --- /dev/null +++ b/app/src/main/java/com/tencent/iot/explorer/link/kitlink/util/BeepManager.java @@ -0,0 +1,112 @@ +package com.tencent.iot.explorer.link.kitlink.util; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.AssetFileDescriptor; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.os.Vibrator; +import android.preference.PreferenceManager; +import android.util.Log; + +import com.example.qrcode.Constant; + +import java.io.Closeable; +import java.io.IOException; + +/** + * Created by yangyu on 17/10/19. + */ + +public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable { + + private static final String TAG = BeepManager.class.getSimpleName(); + + private static final float BEEP_VOLUME = 0.10f; + private static final long VIBRATE_DURATION = 200L; + + private final Activity activity; + private MediaPlayer mediaPlayer; + private boolean playBeep; + private boolean vibrate; + + public BeepManager(Activity activity) { + this.activity = activity; + this.mediaPlayer = null; + updatePrefs(); + } + + public synchronized void updatePrefs() { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); + playBeep = shouldBeep(prefs, activity); + vibrate = prefs.getBoolean(Constant.KEY_VIBRATE, false); + if (playBeep && mediaPlayer == null) { + // The volume on STREAM_SYSTEM is not adjustable, and users found it too loud, + // so we now play on the music stream. + activity.setVolumeControlStream(AudioManager.STREAM_MUSIC); + mediaPlayer = buildMediaPlayer(activity); + } + } + + public synchronized void playBeepSoundAndVibrate() { + if (playBeep && mediaPlayer != null) { + mediaPlayer.start(); + } + if (vibrate) { + Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); + vibrator.vibrate(VIBRATE_DURATION); + } + } + + private static boolean shouldBeep(SharedPreferences prefs, Context activity) { + boolean shouldPlayBeep = prefs.getBoolean(Constant.KEY_PLAY_BEEP, true); + if (shouldPlayBeep) { + // See if sound settings overrides this + AudioManager audioService = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE); + if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) { + shouldPlayBeep = false; + } + } + return shouldPlayBeep; + } + + private MediaPlayer buildMediaPlayer(Context activity) { + MediaPlayer mediaPlayer = new MediaPlayer(); + try (AssetFileDescriptor file = activity.getResources().openRawResourceFd(com.example.qrcode.R.raw.beep)) { + mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); + mediaPlayer.setOnErrorListener(this); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mediaPlayer.setLooping(false); + mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME); + mediaPlayer.prepare(); + return mediaPlayer; + } catch (IOException ioe) { + Log.w(TAG, ioe); + mediaPlayer.release(); + return null; + } + } + + @Override + public synchronized boolean onError(MediaPlayer mp, int what, int extra) { + if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { + // we are finished, so put up an appropriate error toast if required and finish + activity.finish(); + } else { + // possibly media player error, so release and recreate + close(); + updatePrefs(); + } + return true; + } + + @Override + public synchronized void close() { + if (mediaPlayer != null) { + mediaPlayer.release(); + mediaPlayer = null; + } + } + +} diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml index e287bfd0f..088ed851a 100644 --- a/app/src/main/res/values-en-rUS/strings.xml +++ b/app/src/main/res/values-en-rUS/strings.xml @@ -712,6 +712,7 @@ In order for you to scan the code to add devices, Tencent LLink needs to obtain the following permissions: In order to receive the voice/video call function of the device in real time, Tencent LLink needs to obtain the following permissions: In order to make it easier for you to take photos and change your avatar, Tencent LLink needs to obtain the following permissions: + In order to facilitate you to choose the local album QR code picture to add devices, Tencent LLink needs to obtain the following permissions: · Camera · Microphone In order to make it easier for you to take photos to support your feedback, Tencent LLink needs to obtain the following permissions: diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 8c74fa0ed..be27d9642 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -712,6 +712,7 @@ 为了便于您扫码添加设备,因此腾讯连连需获取以下权限: 为了实时接听使用设备的语音/视频通话功能,因此腾讯连连需获取以下权限: 为了便于您拍照更换头像,因此腾讯连连需获取以下权限: + 为了便于您可选择本地相册二维码图片添加设备,因此腾讯连连需获取以下权限: · 相机 · 麦克风 为了便于您拍摄照片用以佐证反馈的问题,因此腾讯连连需获取以下权限: diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8c74fa0ed..be27d9642 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -712,6 +712,7 @@ 为了便于您扫码添加设备,因此腾讯连连需获取以下权限: 为了实时接听使用设备的语音/视频通话功能,因此腾讯连连需获取以下权限: 为了便于您拍照更换头像,因此腾讯连连需获取以下权限: + 为了便于您可选择本地相册二维码图片添加设备,因此腾讯连连需获取以下权限: · 相机 · 麦克风 为了便于您拍摄照片用以佐证反馈的问题,因此腾讯连连需获取以下权限: