From e93bc9e95dd684a863b1026ff94c8ea5600248c3 Mon Sep 17 00:00:00 2001 From: CaiFeng <2397707574@qq.com> Date: Mon, 29 Jan 2024 15:27:39 +0800 Subject: [PATCH 1/3] support permission interface --- README.md | 84 ++++++++++++++++++- .../cloudapp/ui/CasCloudPhoneActivity.java | 44 ++++++---- cloudphone/proguard-rules.pro | 2 + .../cloudphone/api/CloudPhoneParas.java | 4 - .../api/CloudPhonePermissionInfo.java | 36 ++++++++ .../CloudPhonePermissionRequestListener.java | 21 +++++ .../huawei/cloudphone/api/ICloudPhone.java | 14 ++++ .../cloudphone/apiimpl/CloudPhoneImpl.java | 20 +++++ .../virtualdevice/VirtualDeviceSession.java | 9 +- .../virtualdevice/camera/VirtualCamera.java | 1 - .../camera/VirtualCameraManager.java | 23 +++-- .../common/VirtualDeviceManager.java | 7 ++ .../common/VirtualDeviceProtocol.java | 51 ++++++----- .../location/VirtualLocation.java | 15 +++- .../location/VirtualLocationManager.java | 14 +++- .../microphone/VirtualMicrophoneManager.java | 23 +++-- 16 files changed, 300 insertions(+), 68 deletions(-) create mode 100644 cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionInfo.java create mode 100644 cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionRequestListener.java diff --git a/README.md b/README.md index f2dce7b..07715e4 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,87 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' ); ``` -#### 4.11 获取网络时延 + +#### 4.11 注册权限变化监听 + +- 接口介绍 + + void registerPermissionRequestListener(CloudPhonePermissionRequestListener listener); + +- 功能描述 + + 通过注册云手机权限监听回调,实现权限动态申请。 + +- 参数介绍 + + ```java + @param { CloudPhonePermissionRequestListener } listener:云手机权限监听器,接口如下: + + public interface CloudPhonePermissionRequestListener { + void onRequestPermissions(CloudPhonePermissionInfo permissionInfo); + } + + public class CloudPhonePermissionInfo { + private int requestCode; + private String[] permissions; + + public CloudPhonePermissionInfo(int requestCode, String[] permissions) { + this.requestCode = requestCode; + this.permissions = permissions; + } + + public int getRequestCode() { + return this.requestCode; + } + + public String[] getPermissions() { + return this.permissions; + } + } + + 摄像头权限: + requestCode:DEV_TYPE_CAMERA + permissions:{Manifest.permission.CAMERA} + + 麦克风权限: + requestCode:DEV_TYPE_MICROPHONE + permissions:{Manifest.permission.RECORD_AUDIO} + + 定位权限: + requestCode:DEV_TYPE_LOCATION + permissions:{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION} + ``` + +- 调用示例 + + ```java + cloudPhone.registerPermissionRequestListener( + new CloudPhonePermissionRequestListener() { + @Override + public void onRequestPermissions(CloudPhonePermissionInfo permissionInfo) { + // todo + } + } + ); + ``` + +#### 4.12 发送权限申请结果 + +- 接口介绍 + + void sendPermissionResult(int requestCode, int grantResults); + +- 功能描述 + + 发送权限申请结果。 + +- 调用示例 + + ```java + cloudPhone.sendPermissionResult(requestCode, PackageManager.PERMISSION_GRANTED); + ``` + +#### 4.13 获取网络时延 - 接口介绍 @@ -343,7 +423,7 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' cloudPhone.getRtt(); -#### 4.12 双向通道 数据发送接口(支持登录、支付场景) +#### 4.14 双向通道 数据发送接口(支持登录、支付场景) - 接口介绍 diff --git a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java index 64e2c27..b77f3e6 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java @@ -28,6 +28,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; +import androidx.core.app.ActivityCompat; import androidx.fragment.app.FragmentActivity; import android.util.DisplayMetrics; @@ -39,7 +40,6 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; -import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; @@ -61,6 +61,8 @@ import com.huawei.cloudphone.api.CloudAppDataListener; import com.huawei.cloudphone.api.CloudPhoneManager; import com.huawei.cloudphone.api.CloudPhoneOrientationChangeListener; import com.huawei.cloudphone.api.CloudPhoneParas; +import com.huawei.cloudphone.api.CloudPhonePermissionInfo; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.api.CloudPhoneStateListener; import com.huawei.cloudphone.api.ICloudPhone; @@ -99,9 +101,6 @@ import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_CAMERA; import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_LOCATION; import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_MICROPHONE; import static com.huawei.cloudphone.api.CloudPhoneParas.DevType.DEV_PHONE; -import static com.huawei.cloudphone.api.CloudPhoneParas.GRANT_CAMERA_PERMISSION_SUCCESS_ACTION; -import static com.huawei.cloudphone.api.CloudPhoneParas.GRANT_LOCATION_PERMISSION_SUCCESS_ACTION; -import static com.huawei.cloudphone.api.CloudPhoneParas.GRANT_MICROPHONE_PERMISSION_SUCCESS_ACTION; public class CasCloudPhoneActivity extends FragmentActivity { private static final String TAG = "CasCloudPhoneActivity"; @@ -122,6 +121,7 @@ public class CasCloudPhoneActivity extends FragmentActivity { private static final int MSG_CANCLE_EXIT = 107; private static final int MSG_PRESS_HOME = 108; private static final int MSG_PRESS_APP_SWITCH = 109; + private static final int MSG_PERMISSION_REQUEST = 110; private static final int STATE_DEINIT = 1; private static CasListener mCasListener = null; @@ -197,6 +197,9 @@ public class CasCloudPhoneActivity extends FragmentActivity { event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_APP_SWITCH); dispatchKeyEvent(event); break; + case MSG_PERMISSION_REQUEST: + handlePermissionMsg((CloudPhonePermissionInfo) msg.obj); + break; default: break; } @@ -277,6 +280,7 @@ public class CasCloudPhoneActivity extends FragmentActivity { try { mCloudPhone = CloudPhoneManager.createCloudPhoneInstance(); mCloudPhone.setDisplayMode(CloudPhoneParas.DisplayMode.DISPLAY_MODE_FILL); + mCloudPhone.registerPermissionRequestListener(new CloudPhonePermissionRequestListenerImpl()); mCloudPhone.init(this, DEV_PHONE); mCloudPhone.registerCloudPhoneStateListener(new CloudPhoneStateListenerImpl()); @@ -408,17 +412,12 @@ public class CasCloudPhoneActivity extends FragmentActivity { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == DEV_TYPE_CAMERA) { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - this.sendBroadcast(new Intent(GRANT_CAMERA_PERMISSION_SUCCESS_ACTION)); - } - } else if (requestCode == DEV_TYPE_MICROPHONE) { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - this.sendBroadcast(new Intent(GRANT_MICROPHONE_PERMISSION_SUCCESS_ACTION)); - } - } else if (requestCode == DEV_TYPE_LOCATION) { + if (mCloudPhone == null) { + return; + } + if (requestCode == DEV_TYPE_CAMERA || requestCode == DEV_TYPE_MICROPHONE || requestCode == DEV_TYPE_LOCATION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - this.sendBroadcast(new Intent(GRANT_LOCATION_PERMISSION_SUCCESS_ACTION)); + mCloudPhone.sendPermissionResult(requestCode, PackageManager.PERMISSION_GRANTED); } } } @@ -685,6 +684,12 @@ public class CasCloudPhoneActivity extends FragmentActivity { } } + private void handlePermissionMsg(CloudPhonePermissionInfo permissionInfo) { + if (permissionInfo != null) { + ActivityCompat.requestPermissions(this, permissionInfo.getPermissions(), permissionInfo.getRequestCode()); + } + } + /** * determine whether it is a horizontal screen */ @@ -856,6 +861,17 @@ public class CasCloudPhoneActivity extends FragmentActivity { } } + class CloudPhonePermissionRequestListenerImpl implements CloudPhonePermissionRequestListener { + @Override + public void onRequestPermissions(CloudPhonePermissionInfo permissionInfo) { + CASLog.i(TAG, "Permission onRequestPermissions " + permissionInfo.getRequestCode() + permissionInfo.getPermissions()); + Message message = new Message(); + message.what = MSG_PERMISSION_REQUEST; + message.obj = permissionInfo; + handler.sendMessage(message); + } + } + private CasConnectInfo getCasConnectorInfo(String ip, String port, String sessionId, diff --git a/cloudphone/proguard-rules.pro b/cloudphone/proguard-rules.pro index 16502ee..1c1958c 100644 --- a/cloudphone/proguard-rules.pro +++ b/cloudphone/proguard-rules.pro @@ -22,10 +22,12 @@ -ignorewarnings -keep class com.huawei.cloudphone.api.CloudPhoneParas {*;} +-keep class com.huawei.cloudphone.api.CloudPhonePermissionInfo {*;} -keep class com.huawei.cloudphone.api.CloudPhoneManager {*;} -keep interface com.huawei.cloudphone.api.CloudPhoneStateListener {*;} -keep interface com.huawei.cloudphone.api.CloudAppDataListener {*;} -keep interface com.huawei.cloudphone.api.CloudPhoneOrientationChangeListener {*;} +-keep interface com.huawei.cloudphone.api.CloudPhonePermissionRequestListener {*;} -keep interface com.huawei.cloudphone.api.ICloudPhone {*;} -keep public enum com.huawei.cloudphone.api.CloudPhoneParas$* {*;} -keep interface com.huawei.cloudphone.service.CasInteractiveStateCallback {*;} diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhoneParas.java b/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhoneParas.java index eb975c0..1abef36 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhoneParas.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhoneParas.java @@ -31,8 +31,4 @@ public class CloudPhoneParas { public static final short DEV_TYPE_MICROPHONE = 2; public static final short DEV_TYPE_SENSOR = 3; public static final short DEV_TYPE_LOCATION = 4; - - public static final String GRANT_CAMERA_PERMISSION_SUCCESS_ACTION = "android.intent.action.GRANT_CAMERA_PERMISSION_SUCCESS"; - public static final String GRANT_LOCATION_PERMISSION_SUCCESS_ACTION = "android.intent.action.GRANT_LOCATION_PERMISSION_SUCCESS"; - public static final String GRANT_MICROPHONE_PERMISSION_SUCCESS_ACTION = "android.intent.action.GRANT_MICROPHONE_PERMISSION_SUCCESS"; } diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionInfo.java b/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionInfo.java new file mode 100644 index 0000000..777485e --- /dev/null +++ b/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionInfo.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Huawei Cloud Computing Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.cloudphone.api; + +public class CloudPhonePermissionInfo { + + private int requestCode; + private String[] permissions; + + public CloudPhonePermissionInfo(int requestCode, String[] permissions) { + this.requestCode = requestCode; + this.permissions = permissions; + } + + public int getRequestCode() { + return this.requestCode; + } + + public String[] getPermissions() { + return this.permissions; + } +} \ No newline at end of file diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionRequestListener.java b/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionRequestListener.java new file mode 100644 index 0000000..94304e5 --- /dev/null +++ b/cloudphone/src/main/java/com/huawei/cloudphone/api/CloudPhonePermissionRequestListener.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023 Huawei Cloud Computing Technology Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.huawei.cloudphone.api; + +public interface CloudPhonePermissionRequestListener { + + void onRequestPermissions(CloudPhonePermissionInfo permissionInfo); +} \ No newline at end of file diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java b/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java index 5c03089..36c8a48 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/api/ICloudPhone.java @@ -112,6 +112,20 @@ public interface ICloudPhone { */ void sendVirtualDeviceData(byte devType, byte[] data); + /** + * 发送授权结果 + * @param requestCode + * @param grantResults + */ + void sendPermissionResult(int requestCode, int grantResults); + + /** + * 设置权限监听回调 + * + * @param listener + */ + void registerPermissionRequestListener(CloudPhonePermissionRequestListener listener); + /** * 获取网络时延 * diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java b/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java index ad4a4e8..6eef98b 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java @@ -41,6 +41,7 @@ import com.huawei.cloudphone.api.CloudAppDataListener; import com.huawei.cloudphone.api.CloudPhoneOrientationChangeListener; import com.huawei.cloudphone.api.CloudPhoneParas; import com.huawei.cloudphone.api.CloudPhoneParas.DisplayMode; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.api.CloudPhoneStateListener; import com.huawei.cloudphone.api.CloudPhoneVirtualDevDataListener; import com.huawei.cloudphone.api.ICloudPhone; @@ -112,6 +113,7 @@ public class CloudPhoneImpl implements ICloudPhone { private volatile boolean mIsReconnectTaskRun = false; private CloudPhoneStateListener mStateListener = null; private CloudPhoneOrientationChangeListener mOrientationChangeListener = null; + private CloudPhonePermissionRequestListener mPermissionListener = null; private CloudPhoneVirtualDevDataListener mVirtualDevDataListener = null; private CloudAppDataListener mChannelDataListener = null; private CASListener mListener = null; @@ -184,6 +186,7 @@ public class CloudPhoneImpl implements ICloudPhone { mContext = null; mStateListener = null; mOrientationChangeListener = null; + mPermissionListener = null; mChannelDataListener = null; mListener = null; } @@ -298,6 +301,11 @@ public class CloudPhoneImpl implements ICloudPhone { mOrientationChangeListener = listener; } + @Override + public void registerPermissionRequestListener(CloudPhonePermissionRequestListener listener) { + mPermissionListener = listener; + } + @Override public void sendVirtualDeviceData(byte devType, byte[] data) { if (mProccessor != null) { @@ -305,6 +313,15 @@ public class CloudPhoneImpl implements ICloudPhone { } } + @Override + public void sendPermissionResult(int requestCode, int grantResults) { + VirtualDeviceProtocol deviceProtocol = mVirtualDeviceSession.getVirtualDevice(); + if (deviceProtocol == null) { + return; + } + deviceProtocol.processPermissionResult((short) requestCode, grantResults); + } + @Override public int getRtt() { if (mProccessor != null) { @@ -764,6 +781,9 @@ public class CloudPhoneImpl implements ICloudPhone { mVirtualDeviceSession = new VirtualDeviceSession(mContext); mRingBufferVirtualDeviceIO = new RingBufferVirtualDeviceIO(); mVirtualDeviceSession.setVirtualDeviceIoHook(mRingBufferVirtualDeviceIO); + if (mPermissionListener != null) { + mVirtualDeviceSession.setPermissionListener(mPermissionListener); + } mVirtualDevDataListener = new CloudPhoneVirtualDevDataListener() { @Override public void onRecvVirtualDevData(byte[] data, int length) { diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/VirtualDeviceSession.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/VirtualDeviceSession.java index ce0a5eb..ed4013c 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/VirtualDeviceSession.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/VirtualDeviceSession.java @@ -16,15 +16,15 @@ package com.huawei.cloudphone.virtualdevice; import android.content.Context; -import android.hardware.SensorManager; -import android.view.SurfaceHolder; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceIO; import com.huawei.cloudphone.virtualdevice.common.ParamBundle; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol; public class VirtualDeviceSession { VirtualDeviceProtocol mVirtualDevice; + CloudPhonePermissionRequestListener mPermissionListener; Context mContext; ParamBundle mParamBundle; IVirtualDeviceIO mVirtualDeviceIO; @@ -40,6 +40,10 @@ public class VirtualDeviceSession { mVirtualDeviceIO = virtualDeviceIO; } + public void setPermissionListener(CloudPhonePermissionRequestListener listener) { + mPermissionListener = listener; + } + public VirtualDeviceProtocol getVirtualDevice() { if (mVirtualDevice != null) { return mVirtualDevice; @@ -50,6 +54,7 @@ public class VirtualDeviceSession { public void start() { synchronized (mLock) { mVirtualDevice = new VirtualDeviceProtocol(mVirtualDeviceIO, mContext); + mVirtualDevice.initVirtualDeviceManagers(mPermissionListener); mVirtualDevice.startProcess(); } } diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCamera.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCamera.java index 5401b41..f709b26 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCamera.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCamera.java @@ -139,7 +139,6 @@ public class VirtualCamera implements Camera.PreviewCallback { mAvcCodec = new AvcEncoder(mWidth, mHeight, param.getPreviewFrameRate(), mBitrate , new H264DataHandler()); mH264Buffer = new byte[mWidth * mHeight * 3 / 2]; - mAvcCodec.flush(); } mCamera.startPreview(); return 0; diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCameraManager.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCameraManager.java index 6619a3d..e4f1455 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCameraManager.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/camera/VirtualCameraManager.java @@ -28,6 +28,8 @@ import android.util.Log; import androidx.core.app.ActivityCompat; +import com.huawei.cloudphone.api.CloudPhonePermissionInfo; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceDataListener; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceManager; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol; @@ -61,6 +63,7 @@ public class VirtualCameraManager extends VirtualDeviceManager { private VirtualCamera mVirtualCamera; private VirtualDeviceProtocol mVirtualDeviceProtocol; private Context mContext; + private CloudPhonePermissionRequestListener mPermissionListener; private int mWidth; private int mHeight; private int mFrameRate; @@ -76,6 +79,11 @@ public class VirtualCameraManager extends VirtualDeviceManager { mVirtualCamera.stopPreview(); } + @Override + public void setPermissionListener(CloudPhonePermissionRequestListener listener) { + mPermissionListener = listener; + } + public void processMsg(MsgHeader header, byte[] body) { switch (header.mOptType) { case OPT_CAMERA_GET_PARAM_REQ: @@ -147,7 +155,7 @@ public class VirtualCameraManager extends VirtualDeviceManager { mVirtualDeviceProtocol.sendMsg(rspHeader, rspBody, CAMERA_DATA); } - public void initCamera() { + public void init() { if (mVirtualCamera.open(mDevId) != 0) { Log.e(TAG, "initCamera: Failed to open camera"); return; @@ -168,11 +176,16 @@ public class VirtualCameraManager extends VirtualDeviceManager { Context context = mContext.getApplicationContext(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; if (context.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions((Activity) mContext, - new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, - DEV_TYPE_CAMERA); + if (mPermissionListener == null) { + ActivityCompat.requestPermissions((Activity) mContext, + new String[]{Manifest.permission.CAMERA}, + DEV_TYPE_CAMERA); + } else { + mPermissionListener.onRequestPermissions(new CloudPhonePermissionInfo( + DEV_TYPE_CAMERA, new String[]{Manifest.permission.CAMERA})); + } } else { - initCamera(); + init(); } } diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceManager.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceManager.java index 46ad0de..9f823f9 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceManager.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceManager.java @@ -15,6 +15,7 @@ */ package com.huawei.cloudphone.virtualdevice.common; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol.MsgHeader; public class VirtualDeviceManager { @@ -22,9 +23,15 @@ public class VirtualDeviceManager { public void processMsg(MsgHeader header, byte[] body) { } + public void init() { + } + public void start() { } public void stop() { } + + public void setPermissionListener(CloudPhonePermissionRequestListener listener) { + } } diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceProtocol.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceProtocol.java index 5f1af9f..16906a5 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceProtocol.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/common/VirtualDeviceProtocol.java @@ -19,17 +19,12 @@ import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_CAMERA; import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_LOCATION; import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_MICROPHONE; import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_SENSOR; -import static com.huawei.cloudphone.api.CloudPhoneParas.GRANT_CAMERA_PERMISSION_SUCCESS_ACTION; -import static com.huawei.cloudphone.api.CloudPhoneParas.GRANT_LOCATION_PERMISSION_SUCCESS_ACTION; -import static com.huawei.cloudphone.api.CloudPhoneParas.GRANT_MICROPHONE_PERMISSION_SUCCESS_ACTION; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.hardware.SensorManager; import android.util.Log; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.virtualdevice.camera.VirtualCameraManager; import com.huawei.cloudphone.virtualdevice.location.VirtualLocationManager; import com.huawei.cloudphone.virtualdevice.microphone.VirtualMicrophoneManager; @@ -48,26 +43,13 @@ public class VirtualDeviceProtocol { static Object mSendMsgLock = new Object(); private Map virtualDeviceManagers; private Context mContext; - private BroadcastReceiver mPermissionResultReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (GRANT_CAMERA_PERMISSION_SUCCESS_ACTION.equals(intent.getAction())) { - ((VirtualCameraManager)virtualDeviceManagers.get(DEV_TYPE_CAMERA)).initCamera(); - } else if (GRANT_MICROPHONE_PERMISSION_SUCCESS_ACTION.equals(intent.getAction())) { - ((VirtualMicrophoneManager)virtualDeviceManagers.get(DEV_TYPE_MICROPHONE)).initMicrophone(); - } else if (GRANT_LOCATION_PERMISSION_SUCCESS_ACTION.equals(intent.getAction())) { - ((VirtualLocationManager)virtualDeviceManagers.get(DEV_TYPE_LOCATION)).initLocation(); - } - } - }; - public VirtualDeviceProtocol(IVirtualDeviceIO virtualDeviceIO ,Context context) { + public VirtualDeviceProtocol(IVirtualDeviceIO virtualDeviceIO , Context context) { mVirtualDeviceIO = virtualDeviceIO; mContext = context; - initVirtualDeviceManagers(); } - private void initVirtualDeviceManagers() { + public void initVirtualDeviceManagers(CloudPhonePermissionRequestListener listener) { virtualDeviceManagers = new HashMap(); virtualDeviceManagers.put(DEV_TYPE_CAMERA, new VirtualCameraManager(this, mContext)); virtualDeviceManagers.put(DEV_TYPE_MICROPHONE, new VirtualMicrophoneManager(this, mContext)); @@ -75,11 +57,12 @@ public class VirtualDeviceProtocol { (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE))); virtualDeviceManagers.put(DEV_TYPE_LOCATION, new VirtualLocationManager(this, mContext)); - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(GRANT_CAMERA_PERMISSION_SUCCESS_ACTION); - intentFilter.addAction(GRANT_MICROPHONE_PERMISSION_SUCCESS_ACTION); - intentFilter.addAction(GRANT_LOCATION_PERMISSION_SUCCESS_ACTION); - mContext.registerReceiver(mPermissionResultReceiver, intentFilter); + // 设置权限监听 + if (listener != null) { + ((VirtualCameraManager)virtualDeviceManagers.get(DEV_TYPE_CAMERA)).setPermissionListener(listener); + ((VirtualMicrophoneManager)virtualDeviceManagers.get(DEV_TYPE_MICROPHONE)).setPermissionListener(listener); + ((VirtualLocationManager)virtualDeviceManagers.get(DEV_TYPE_LOCATION)).setPermissionListener(listener); + } } public VirtualDeviceManager getVirtualDeviceManager(short devType) { @@ -89,6 +72,17 @@ public class VirtualDeviceProtocol { return virtualDeviceManagers.get(devType); } + public void processPermissionResult(short requestCode, int grantResult) { + if (grantResult != 0) { + return; + } + VirtualDeviceManager deviceManager = virtualDeviceManagers.get(requestCode); + if (deviceManager == null) { + return; + } + deviceManager.init(); + } + public void processMsg(MsgHeader header, byte[] body) { short devType = header.mDeviceType; if (devType == 0) devType = DEV_TYPE_SENSOR; @@ -115,7 +109,6 @@ public class VirtualDeviceProtocol { for (Map.Entry entry : virtualDeviceManagers.entrySet()) { entry.getValue().stop(); } - mContext.unregisterReceiver(mPermissionResultReceiver); } public void sendMsg(MsgHeader header, byte[] body, int deviceType) { @@ -188,6 +181,10 @@ public class VirtualDeviceProtocol { } MsgHeader msgHeader = new MsgHeader(header); int bodyLen = msgHeader.mPayloadLength; + if (bodyLen < 0) { + Log.e(TAG, "Read msg header error, bodyLen = " + bodyLen); + continue; + } byte[] body = new byte[bodyLen]; if (readN(body, 0, bodyLen) != bodyLen) { Log.e(TAG, "Read msg header error"); diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocation.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocation.java index ef87726..baef697 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocation.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocation.java @@ -46,6 +46,8 @@ import android.telephony.TelephonyManager; import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; +import com.huawei.cloudphone.api.CloudPhonePermissionInfo; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.common.CASLog; import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceDataListener; @@ -74,13 +76,18 @@ public class VirtualLocation { @RequiresApi(api = Build.VERSION_CODES.P) @SuppressLint("MissingPermission") - public void requestLocationUpdates() { + public void requestLocationUpdates(CloudPhonePermissionRequestListener listener) { if ((ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) && (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { CASLog.i(TAG, "request coarse and fine location permission"); - ActivityCompat.requestPermissions((Activity) mContext, - new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, - DEV_TYPE_LOCATION); + if (listener == null) { + ActivityCompat.requestPermissions((Activity) mContext, + new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, + DEV_TYPE_LOCATION); + } else { + listener.onRequestPermissions(new CloudPhonePermissionInfo( + DEV_TYPE_LOCATION, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})); + } } else { if (mLocationManager == null) { mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocationManager.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocationManager.java index f0d8ea0..582bedf 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocationManager.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/location/VirtualLocationManager.java @@ -10,7 +10,7 @@ import android.util.Log; import androidx.annotation.RequiresApi; -import com.huawei.cloudphone.common.CASLog; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceDataListener; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceManager; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol; @@ -23,6 +23,7 @@ public class VirtualLocationManager extends VirtualDeviceManager { private VirtualLocation mVirtualLocation; private VirtualDeviceProtocol mVirtualDeviceProtocol; + private CloudPhonePermissionRequestListener mPermissionListener; public VirtualLocationManager(VirtualDeviceProtocol virtualDeviceProtocol, Context context) { mVirtualDeviceProtocol = virtualDeviceProtocol; @@ -30,9 +31,14 @@ public class VirtualLocationManager extends VirtualDeviceManager { mVirtualLocation.registerLocationDataListener(new LocationDataListener()); } + @Override + public void setPermissionListener(CloudPhonePermissionRequestListener listener) { + mPermissionListener = listener; + } + @RequiresApi(api = Build.VERSION_CODES.P) - public void initLocation() { - mVirtualLocation.requestLocationUpdates(); + public void init() { + mVirtualLocation.requestLocationUpdates(mPermissionListener); } public void stop() { @@ -44,7 +50,7 @@ public class VirtualLocationManager extends VirtualDeviceManager { switch (header.mOptType) { case OPT_LOCATION_OPEN_REQ: Log.i(TAG, "processMsg: open location"); - mVirtualLocation.requestLocationUpdates(); + mVirtualLocation.requestLocationUpdates(mPermissionListener); break; case OPT_LOCATION_CLOSE_REQ: Log.i(TAG, "processMsg: close location"); diff --git a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/microphone/VirtualMicrophoneManager.java b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/microphone/VirtualMicrophoneManager.java index eb02ca9..2f6ff0f 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/microphone/VirtualMicrophoneManager.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/virtualdevice/microphone/VirtualMicrophoneManager.java @@ -32,6 +32,8 @@ import android.util.Log; import androidx.core.app.ActivityCompat; +import com.huawei.cloudphone.api.CloudPhonePermissionInfo; +import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener; import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceDataListener; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceManager; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol; @@ -58,6 +60,7 @@ public class VirtualMicrophoneManager extends VirtualDeviceManager { private VirtualMicrophone mVirtualMicrophone; private VirtualDeviceProtocol mVirtualDeviceProtocol; private Context mContext; + private CloudPhonePermissionRequestListener mPermissionListener; public VirtualMicrophoneManager(VirtualDeviceProtocol virtualDeviceProtocol, Context context) { mVirtualDeviceProtocol = virtualDeviceProtocol; @@ -65,6 +68,11 @@ public class VirtualMicrophoneManager extends VirtualDeviceManager { mContext = context; } + @Override + public void setPermissionListener(CloudPhonePermissionRequestListener listener) { + mPermissionListener = listener; + } + public void processMsg(MsgHeader header, byte[] msgBody) { switch (header.mOptType) { case OPT_MICROPHONE_START_RECORD_REQ: @@ -82,7 +90,7 @@ public class VirtualMicrophoneManager extends VirtualDeviceManager { } } - public void initMicrophone() { + public void init() { mVirtualMicrophone.setOnRecvDataListener(new MicrophoneDataListener()); int result = mVirtualMicrophone.start(); if (result != 0) { @@ -102,11 +110,16 @@ public class VirtualMicrophoneManager extends VirtualDeviceManager { Context context = mContext.getApplicationContext(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; if (context.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions((Activity) mContext, - new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, - DEV_TYPE_MICROPHONE); + if (mPermissionListener == null) { + ActivityCompat.requestPermissions((Activity) mContext, + new String[]{Manifest.permission.RECORD_AUDIO}, + DEV_TYPE_MICROPHONE); + } else { + mPermissionListener.onRequestPermissions(new CloudPhonePermissionInfo( + DEV_TYPE_MICROPHONE, new String[]{Manifest.permission.RECORD_AUDIO})); + } } else { - initMicrophone(); + init(); } } -- Gitee From 0944668765be14726694a86169bbaeab742cf8cb Mon Sep 17 00:00:00 2001 From: CaiFeng <2397707574@qq.com> Date: Mon, 29 Jan 2024 15:30:46 +0800 Subject: [PATCH 2/3] support permission interface, fix readme --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 07715e4..60ce180 100644 --- a/README.md +++ b/README.md @@ -343,7 +343,7 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' - 参数介绍 ```java - @param { CloudPhonePermissionRequestListener } listener:云手机权限监听器,接口如下: + @param { CloudPhonePermissionRequestListener } listener: 云手机权限监听器,接口如下: public interface CloudPhonePermissionRequestListener { void onRequestPermissions(CloudPhonePermissionInfo permissionInfo); @@ -367,17 +367,17 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' } } - 摄像头权限: - requestCode:DEV_TYPE_CAMERA - permissions:{Manifest.permission.CAMERA} + 摄像头权限: + requestCode: DEV_TYPE_CAMERA + permissions: {Manifest.permission.CAMERA} - 麦克风权限: - requestCode:DEV_TYPE_MICROPHONE - permissions:{Manifest.permission.RECORD_AUDIO} + 麦克风权限: + requestCode: DEV_TYPE_MICROPHONE + permissions: {Manifest.permission.RECORD_AUDIO} - 定位权限: - requestCode:DEV_TYPE_LOCATION - permissions:{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION} + 定位权限: + requestCode: DEV_TYPE_LOCATION + permissions: {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION} ``` - 调用示例 @@ -433,7 +433,7 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' 发送数据给云手机中运行的游戏或应用 -#### 4.13 双向通道 数据接收监听接口(支持登录、支付场景) +#### 4.15 双向通道 数据接收监听接口(支持登录、支付场景) - 接口介绍 -- Gitee From b3798047f7b04b66834d68c814f291d2651b1f67 Mon Sep 17 00:00:00 2001 From: CaiFeng <2397707574@qq.com> Date: Mon, 29 Jan 2024 15:31:22 +0800 Subject: [PATCH 3/3] support permission interface, fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60ce180..abeee5b 100644 --- a/README.md +++ b/README.md @@ -343,7 +343,7 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' - 参数介绍 ```java - @param { CloudPhonePermissionRequestListener } listener: 云手机权限监听器,接口如下: + @param { CloudPhonePermissionRequestListener } listener: 云手机权限监听器, 接口如下: public interface CloudPhonePermissionRequestListener { void onRequestPermissions(CloudPhonePermissionInfo permissionInfo); -- Gitee