diff --git a/README.md b/README.md index f2dce7ba2236819531039d332c1ce52074c38f31..abeee5b4b7815af0aa9e2c29f790dc8bfd6b94ed 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 双向通道 数据发送接口(支持登录、支付场景) - 接口介绍 @@ -353,7 +433,7 @@ implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' 发送数据给云手机中运行的游戏或应用 -#### 4.13 双向通道 数据接收监听接口(支持登录、支付场景) +#### 4.15 双向通道 数据接收监听接口(支持登录、支付场景) - 接口介绍 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 64e2c2701d76281575937481834f7a9c7d8c9af9..b77f3e61be627d12d24fa6b7a36da8211650be2c 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 16502ee4d75eb7083622cdb8ecb904391baddb70..1c1958c1b00b5a6a897c1656cd4aa8bdb7ef7663 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 eb975c0f27e07d734bf20816637eca5c185775ef..1abef3663c31777417328c7886a2987f65d9312c 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 0000000000000000000000000000000000000000..777485e57bb1059d18e480bfe035e967faf64595 --- /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 0000000000000000000000000000000000000000..94304e5f763b4476d38dfde713000b74241ec96a --- /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 5c03089ddc2f3f88ca55935d80fbc91cee6e4d6c..36c8a482a584358adadbb62066cf081a60fa147a 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 ad4a4e806da2510fe3c853f1bc300f4d3fc73706..6eef98b3e9176158d1d4cf820d755bb993837d91 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 ce0a5eb3b81eac797c042e3e4ab2199dcf0ba9bf..ed4013c60f8826b5f2d407654f7a0f505335f829 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 5401b4160c2594984cdaa7cca0baf333a5c300de..f709b26d7bb9836dbdaa92eb1e10f381ff5022ed 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 6619a3df70b0119811bc99d33907612bb13598b8..e4f14552406bc3eec08bcf2eefa0a093a838b714 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 46ad0de63f0e5e89f300a4f14e1d238e2871fb18..9f823f999f48ef225e22909b18d4bd5f5bb84fd7 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 5f1af9fd6cb3d5768465fcceaa7069c9a79afddf..16906a5ac97aca5931b60a17aba8351617847163 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 ef877262225d06280dd3e82281d29c606d4685b4..baef69718cb5b9cc64882fb2872276875041c760 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 f0d8ea037e7367cf85dc6b220ba6a26b343a85a8..582bedf924bd167f053fdd955735367c2bb1f83b 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 eb02ca90128dc1527da37bca6bb041c7e9525058..2f6ff0fa20bab2afac5eca57ad99b6d44ae50805 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(); } }