diff --git a/app/src/main/java/com/huawei/cloudapp/model/management/ConnectInfoModel.java b/app/src/main/java/com/huawei/cloudapp/model/management/ConnectInfoModel.java index d80c021cb8f49070980e02ad0a705be1dfead290..7753783c956c018927d970288e3a99e1c71baac1 100644 --- a/app/src/main/java/com/huawei/cloudapp/model/management/ConnectInfoModel.java +++ b/app/src/main/java/com/huawei/cloudapp/model/management/ConnectInfoModel.java @@ -5,6 +5,7 @@ import static com.huawei.cloudapp.utils.CasConstantsUtil.ALLOCATION; import static com.huawei.cloudapp.utils.CasConstantsUtil.AVAILABLE_PLAYTIME; import static com.huawei.cloudapp.utils.CasConstantsUtil.BACKGROUND_TIMEOUT; import static com.huawei.cloudapp.utils.CasConstantsUtil.CLIENT_TYPE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.CLOUD_PHONE_ID; import static com.huawei.cloudapp.utils.CasConstantsUtil.CONNECTION; import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_MSG; @@ -45,12 +46,10 @@ import okhttp3.Response; public class ConnectInfoModel implements IConnectInfoModel { public static final String TAG = "ConnectInfoModel"; - private String mPhoneId; @Override public void getConnectInfo(User user, String phoneId, String region, OnRequestListener onRequestListener) { String url = getManagementUrl() + "/" + CONNECTION + "/" + ALLOCATION; - mPhoneId = phoneId; HashMap requestBody = new HashMap(); requestBody.put(PHONE_ID, phoneId); requestBody.put(CLIENT_TYPE, "ANDROID"); @@ -102,6 +101,12 @@ public class ConnectInfoModel implements IConnectInfoModel { } } + if (!rspMap.containsKey(CLOUD_PHONE_ID) || !CasCommonUtils.isValidUUID((String) rspMap.get(CLOUD_PHONE_ID))) { + Log.e(TAG, "The cloud_phone_id is invalid."); + throw new CustomException.ResponseParamsException(); + } + String cloudPhoneId = (String) rspMap.get(CLOUD_PHONE_ID); + if (!rspMap.containsKey(IP) || !rspMap.containsKey(PORT) || !rspMap.containsKey(SESSION_ID)) { Log.e(TAG, "The start param is invalid."); throw new CustomException.ResponseParamsException(); @@ -143,11 +148,12 @@ public class ConnectInfoModel implements IConnectInfoModel { throw new CustomException.ResponseParamsException(); } - CasConnectInfo mConnectInfo = GenerateConnectInfo(ip, port, sessionId, backgroundTimeout, availablePlaytime, touchTimeout); + CasConnectInfo mConnectInfo = GenerateConnectInfo(cloudPhoneId, ip, port, sessionId, backgroundTimeout, availablePlaytime, touchTimeout); return Collections.singletonList(mConnectInfo); } - public CasConnectInfo GenerateConnectInfo(String ip, + public CasConnectInfo GenerateConnectInfo(String cloudPhoneId, + String ip, String port, String sessionId, String backgroundTimeout, @@ -162,13 +168,12 @@ public class ConnectInfoModel implements IConnectInfoModel { CasConnectInfo connectorInfo = new CasConnectInfo(); connectorInfo.setConnectIp(ip); connectorInfo.setConnectPort(port); - connectorInfo.setBackgroundTimeout(backgroundTimeout.isEmpty() ? "60" : backgroundTimeout); + connectorInfo.setBackgroundTimeout(backgroundTimeout.isEmpty() ? "3600" : backgroundTimeout); connectorInfo.setAvailablePlayTime(availablePlayTime.isEmpty() ? "0" : availablePlayTime); connectorInfo.setSessionId(sessionId); connectorInfo.setTicket("ticket_xxxxxx"); - connectorInfo.setAesKey("11111111111111111111111111111111"); - connectorInfo.setAesKey(mPhoneId); - connectorInfo.setAuthTs("987654321"); + connectorInfo.setAesKey(cloudPhoneId); + connectorInfo.setAuthTs(String.valueOf(System.currentTimeMillis())); connectorInfo.setTouchTimeout(touchTimeout.isEmpty() ? "0" : touchTimeout); return connectorInfo; } diff --git a/app/src/main/java/com/huawei/cloudapp/model/management/UserModel.java b/app/src/main/java/com/huawei/cloudapp/model/management/UserModel.java index 72988834e2260dd8fbd3af8cd818467907ae7650..5b35092d2f9a5f951b58e0591d6025b5d2ca4eec 100644 --- a/app/src/main/java/com/huawei/cloudapp/model/management/UserModel.java +++ b/app/src/main/java/com/huawei/cloudapp/model/management/UserModel.java @@ -43,7 +43,7 @@ public class UserModel implements IUserModel { @Override public void getUser(User user, String password, String region, final OnRequestListener onRequestListener) { Map userInfo = new HashMap<>(); - userInfo.put(USERNAME, user.getUsername()); + userInfo.put(USERNAME, user.getIamUsername()); userInfo.put(PASSWORD, password); Gson gson = new Gson(); String userInfoJson = gson.toJson(userInfo); diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java index 5ccf1b3a97ec8436cb2f1c64f82046926912bad9..0aaf9ac043705c30b938816f3a5b8a97a849bfa2 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java @@ -277,46 +277,46 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa mProgressBar = findViewById(R.id.loading_progress_bar); mFrameLayout = (FrameLayout) findViewById(R.id.frame_layout); - mMiniStatisticsTextView = findViewById(R.id.cas_mini_statistic_view); - mMiniStatisticsTextView.setTextColor(Color.argb(255, 216, 234, 196)); +// mMiniStatisticsTextView = findViewById(R.id.cas_mini_statistic_view); +// mMiniStatisticsTextView.setTextColor(Color.argb(255, 216, 234, 196)); mStatisticsTextView = findViewById(R.id.cas_statistic_view); mStatisticsTextView.setTextColor(Color.GREEN); - mStatisticsCheckBox = findViewById(R.id.cas_stats_checkBox); - mStatisticsCheckBox.setTextColor(Color.GREEN); - mStatisticsCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (isChecked) { - mStatisticsTextView.setVisibility(View.VISIBLE); - float density = getResources().getDisplayMetrics().density; - mStatisticsTextView.setHeight((int) (50 * density)); - } else { - mStatisticsTextView.setVisibility(View.INVISIBLE); - } - }); - mTimer.schedule(new TimerTask() { - @Override - public void run() { - runOnUiThread(() -> { - onUpdateSensorInfo(); - onUpdateStatisticInfo(); - }); - } - }, 1000, 1000); +// mStatisticsCheckBox = findViewById(R.id.cas_stats_checkBox); +// mStatisticsCheckBox.setTextColor(Color.GREEN); +// mStatisticsCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { +// if (isChecked) { +// mStatisticsTextView.setVisibility(View.VISIBLE); +// float density = getResources().getDisplayMetrics().density; +// mStatisticsTextView.setHeight((int) (50 * density)); +// } else { +// mStatisticsTextView.setVisibility(View.INVISIBLE); +// } +// }); +// mTimer.schedule(new TimerTask() { +// @Override +// public void run() { +// runOnUiThread(() -> { +// onUpdateSensorInfo(); +// onUpdateStatisticInfo(); +// }); +// } +// }, 1000, 1000); mSensorInfoTextView = findViewById(R.id.cas_sensor_view); mSensorInfoTextView.setTextColor(Color.GREEN); - mSensorInfoCheckBox = findViewById(R.id.cas_sensor_checkBox); - mSensorInfoCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (isChecked) { - mSensorInfoTextView.setVisibility(View.VISIBLE); - float density = getResources().getDisplayMetrics().density; - mSensorInfoTextView.setHeight((int) (50 * density)); - } else { - mSensorInfoTextView.setVisibility(View.INVISIBLE); - } - }); +// mSensorInfoCheckBox = findViewById(R.id.cas_sensor_checkBox); +// mSensorInfoCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { +// if (isChecked) { +// mSensorInfoTextView.setVisibility(View.VISIBLE); +// float density = getResources().getDisplayMetrics().density; +// mSensorInfoTextView.setHeight((int) (50 * density)); +// } else { +// mSensorInfoTextView.setVisibility(View.INVISIBLE); +// } +// }); if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{ @@ -476,20 +476,7 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa handler.sendMessage(message); } - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); - if (clipboardManager.hasPrimaryClip() && clipboardManager.getPrimaryClip().getItemCount() > 0) { - CharSequence charSequence = clipboardManager.getPrimaryClip().getItemAt(0).getText(); - try { - mCloudPhone.sendClipboardData(charSequence.toString().getBytes()); - } catch (Exception e) { - CASLog.i(TAG, "failed to send clipboard data " + e.getMessage()); - } - } - } - }, 100); + sendClipboardData(); } /** @@ -569,6 +556,9 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa } showDialog(getResources().getString(R.string.cas_phone_invalid_cmd_tip_message)); break; + case CasState.CAS_VERIFY_SUCCESS: + sendClipboardData(); + break; case CasState.CAS_VERIFY_PARAMETER_MISSING: case CasState.CAS_VERIFY_PARAMETER_INVALID: case CasState.CAS_VERIFY_AESKEY_QUERY_FAILED: @@ -901,6 +891,23 @@ public class CasCloudPhoneActivity extends FragmentActivity implements IHandleDa } } + public void sendClipboardData() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + if (clipboardManager.hasPrimaryClip() && clipboardManager.getPrimaryClip().getItemCount() > 0) { + CharSequence charSequence = clipboardManager.getPrimaryClip().getItemAt(0).getText(); + try { + mCloudPhone.sendClipboardData(charSequence.toString().getBytes()); + } catch (Exception e) { + CASLog.e(TAG, "failed to send clipboard data " + e.getMessage()); + } + } + } + }, 300); + } + /** * 启动成功后处理任务 */ diff --git a/app/src/main/java/com/huawei/cloudapp/utils/CasConstantsUtil.java b/app/src/main/java/com/huawei/cloudapp/utils/CasConstantsUtil.java index 3ecbdc9b5457b89a066254a142b0fd5b2e4e8c5c..3fde14c87c738bce550ab6153eebc8b3a5040f53 100644 --- a/app/src/main/java/com/huawei/cloudapp/utils/CasConstantsUtil.java +++ b/app/src/main/java/com/huawei/cloudapp/utils/CasConstantsUtil.java @@ -51,6 +51,8 @@ public class CasConstantsUtil { public static final String PHONE_ID = "phone_id"; + public static final String CLOUD_PHONE_ID = "cloud_phone_id"; + public static final String PHONE_NAME = "phone_name"; public static final String REGION_ID = "region_id"; @@ -221,7 +223,7 @@ public class CasConstantsUtil { public static final String PERSONAL = "personal"; public static final String ENTERPRISE = "enterprise"; - public static final String MANAGEMENT_DEV_ENV_URL = "https://140.210.196.28:18000"; + public static final String MANAGEMENT_DEV_ENV_URL = "https://139.9.235.129:18000"; public static final String MANAGEMENT_PROD_ENV_URL = "https://139.9.146.101:18000"; public static final String PHONE = "phone"; public static final String LIST = "list"; diff --git a/app/src/main/res/layout/cas_activity_fullscreen.xml b/app/src/main/res/layout/cas_activity_fullscreen.xml index 9684316e8ee7d02cccd2e7325ec2d6ca030709e7..d6253da833436b1804b58908a82491593128ca70 100644 --- a/app/src/main/res/layout/cas_activity_fullscreen.xml +++ b/app/src/main/res/layout/cas_activity_fullscreen.xml @@ -19,27 +19,27 @@ android:layout_width="match_parent" android:layout_height="match_parent"/> - + + + + + + + - + + + + + + + - + + + + + - CPH-24.7.0 + 华为云云手机 CasCloudAppMainActivity GameListActivity GameListActivity2 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 9513cbffa472cbbe16183f26f0874330adeec96c..2a8fbd41e6edffdaba9cecec713f89b2e5b0fe50 100644 --- a/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java +++ b/cloudphone/src/main/java/com/huawei/cloudphone/apiimpl/CloudPhoneImpl.java @@ -66,8 +66,11 @@ import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceManager; import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol; import com.huawei.cloudphone.virtualdevice.sensor.VirtualSensorManager; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Timer; import java.util.TimerTask; @@ -95,6 +98,7 @@ public class CloudPhoneImpl implements ICloudPhone { private static final byte CUSTOM_DATA = 18; private static final byte IME_DATA =14; public static final int RECONNECT_RETRY_MAX_COUNT = 10; + public static final int SEND_IME_DATA_RETRY_MAX_COUNT = 100; // 300ms*100,与重连总时长保持一致 public static final int RECONNECT_INTERVAL_TIME = 2; // 间隔2s,实际执行为3s private final Object mCloudPhoneLock = new Object(); @@ -131,6 +135,7 @@ public class CloudPhoneImpl implements ICloudPhone { private int mTouchCount = 0; private VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private Toast toast = null; + private int surfaceId = -1; // 避免快速连接时新的窗口已建立,旧的窗口执行销毁操作发送pause private long initTime = 0; @@ -403,14 +408,26 @@ public class CloudPhoneImpl implements ICloudPhone { mSurfaceView = new PhoneView(activity, false); } mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { + private int curSurfaceId; + @Override public void surfaceCreated(SurfaceHolder holder) { - CASLog.i(TAG, "surfaceCreated..."); + SecureRandom random = new SecureRandom(); + curSurfaceId = random.nextInt(1000); + while (curSurfaceId == surfaceId) { + curSurfaceId = random.nextInt(1000); + } + surfaceId = curSurfaceId; + CASLog.i(TAG, "surfaceCreated, surfaceId:" + this.curSurfaceId); mIsNewCreated = true; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (this.curSurfaceId != surfaceId) { + CASLog.w(TAG, "cancel surfaceChanged(). curSurfaceId:" + this.curSurfaceId + ", surfaceId:" + surfaceId); + return; + } mDisplayWidth = Math.min(width, height); mDisplayHeight = Math.max(width, height); @@ -438,9 +455,13 @@ public class CloudPhoneImpl implements ICloudPhone { @Override public void surfaceDestroyed(SurfaceHolder holder) { + if (this.curSurfaceId != surfaceId) { + CASLog.w(TAG, "cancel surfaceDestroyed(). curSurfaceId:" + this.curSurfaceId + ", surfaceId:" + surfaceId); + return; + } synchronized (mCloudPhoneLock) { try { - CASLog.i(TAG, "surfaceDestroyed..."); + CASLog.i(TAG, "surfaceDestroyed, surfaceId:" + surfaceId); if (mProccessor != null && mProccessor.getState() != JNIState.JNI_STOPPED) { mProccessor.stop(true); } @@ -1003,6 +1024,22 @@ public class CloudPhoneImpl implements ICloudPhone { class TextWatchListener implements CloudPhoneTextWatchListener { @Override public void onTextChange(byte[] data) { + int tryCount = 0; + if (mCurrentState != STATE_START) { + return; + } + while (!mProccessor.isConnect() || mProccessor.getState() != JNIState.JNI_CONNECTED) { + if (tryCount >= SEND_IME_DATA_RETRY_MAX_COUNT) { + CASLog.e(TAG, "onTextChange retry failed. processor connect:" + mProccessor.isConnect() + ", processor state:" + mProccessor.getState()); + return; + } + try { + Thread.sleep(300); + } catch (InterruptedException e) { + e.printStackTrace(); + } + tryCount++; + } mProccessor.sendData(JNIWrapper.IMEDATA, data); } } diff --git a/config.gradle b/config.gradle index c8bf37cda0f0cf84aae36c0a9b48cfa934fe9c94..3dcc74bee04fc29cdc9391b98dd58c001ab90f03 100644 --- a/config.gradle +++ b/config.gradle @@ -5,5 +5,5 @@ ext.versions = [ compileSdkVersion : 31, buildToolsVersion : '28.0.3', versionCode : 1, - versionName : '24.7.0', + versionName : '24.8.1', ] \ No newline at end of file