diff --git a/app/build.gradle b/app/build.gradle index 4c0274f37b7bb29e40e9acb97e7c86ef480da40d..4dcd9d140ff1defa9ebf99157e6f6112c2ac370e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,6 +10,7 @@ android { versionCode versions.versionCode versionName versions.versionName archivesBaseName = "CloudApp_" + versionName + buildConfigField "boolean", "IS_DIRECT_MODE", "true" } lintOptions { @@ -64,6 +65,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + viewBinding { + enabled true + } } dependencies { @@ -72,13 +76,23 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.github.bumptech.glide:glide:4.13.0' implementation 'androidx.cardview:cardview:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' + implementation 'androidx.navigation:navigation-fragment:2.3.0' + implementation 'androidx.navigation:navigation-ui:2.3.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.14.0' - implementation 'com.hyman:flowlayout-lib:1.1.2' - implementation 'com.github.Petterpx:FloatingX:1.3.3' implementation 'com.android.support:design:28.0.0' - implementation 'com.github.shem8:material-login:2.1.1' - implementation 'com.github.Justson.AgentWeb:agentweb-core:v5.0.6-androidx' + implementation'com.android.support:support-v4:28.0.0' implementation 'org.bouncycastle:bcprov-jdk15to18:1.71' implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.10.0' + implementation 'com.google.android.material:material:1.6.1' + implementation 'io.github.scwang90:refresh-layout-kernel:2.1.0' + implementation 'io.github.scwang90:refresh-header-classics:2.1.0' + implementation 'io.github.scwang90:refresh-footer-classics:2.1.0' + implementation "io.github.cymchad:BaseRecyclerViewAdapterHelper:3.0.14" + implementation 'com.github.getActivity:Toaster:12.6' + implementation 'com.github.Justson.AgentWeb:agentweb-core:v5.0.6-androidx' + implementation "com.kongzue.dialogx:DialogX:0.0.49" implementation project(':cloudphone') -} +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5575ca1a46bee3c88af2757865851f4567af68f5..7aed78d0347f6136a4dc16c13a3b2efbcfa641db 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,51 +11,71 @@ - + android:theme="@style/AppTheme"> + + + + + android:windowSoftInputMode="adjustResize" /> + + - - + + + \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/common/CasCommonDialog.java b/app/src/main/java/com/huawei/cloudapp/common/CasCommonDialog.java index 178f00dc042e37ba502b606e0ad5cb155f4a718e..0a21b39e683e3199252fd30fcd24400cf39cb1eb 100644 --- a/app/src/main/java/com/huawei/cloudapp/common/CasCommonDialog.java +++ b/app/src/main/java/com/huawei/cloudapp/common/CasCommonDialog.java @@ -19,6 +19,7 @@ package com.huawei.cloudapp.common; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup.LayoutParams; @@ -50,6 +51,7 @@ public class CasCommonDialog extends Dialog { private String negativeButtonText; private OnClickListener positiveButtonClickListener; private OnClickListener negativeButtonClickListener; + private int contentGravity; public Builder(Context context) { this.context = context; @@ -104,6 +106,11 @@ public class CasCommonDialog extends Dialog { return this; } + public Builder setGravity(int gravity) { + this.contentGravity = gravity; + return this; + } + public CasCommonDialog create() { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); final CasCommonDialog dialog = new CasCommonDialog(context, R.style.dialog); @@ -144,6 +151,9 @@ public class CasCommonDialog extends Dialog { } TextView messageTV = (TextView) layout.findViewById(R.id.message); + if (contentGravity != 0) { + messageTV.setGravity(contentGravity); + } LinearLayout content = (LinearLayout) layout.findViewById(R.id.content); if (message != null) { messageTV.setText(message); diff --git a/app/src/main/java/com/huawei/cloudapp/common/CasRecord.java b/app/src/main/java/com/huawei/cloudapp/common/CasRecord.java index 496873f8ae04d5e093eca64346cc7a24e58c3b7f..d4edf8010d075d1cddd562ef5c6671e16e7843a6 100644 --- a/app/src/main/java/com/huawei/cloudapp/common/CasRecord.java +++ b/app/src/main/java/com/huawei/cloudapp/common/CasRecord.java @@ -18,7 +18,12 @@ package com.huawei.cloudapp.common; import android.content.SharedPreferences; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; import java.util.Arrays; +import java.util.HashMap; public class CasRecord { @@ -57,4 +62,24 @@ public class CasRecord { } } + public String getRecord(String key) { + return mPreferences.getString(key, ""); + } + + public void setRecord(String key, String value) { + mPreferences.edit().putString(key, value).apply(); + } + public void setHashMapRecord(String key, HashMap value) { + Gson gson = new Gson(); + String json = gson.toJson(value); + mPreferences.edit().putString(key, json).apply(); + } + + public HashMap getHashMapRecord(String key) { + String json = mPreferences.getString(key, ""); + Gson gson = new Gson(); + Type type = new TypeToken>(){}.getType(); + return gson.fromJson(json, type); + } + } diff --git a/app/src/main/java/com/huawei/cloudapp/common/CasState.java b/app/src/main/java/com/huawei/cloudapp/common/CasState.java index 5839fffe5da7984175cf7e4400317c8f43cf89d1..4831f3506d9b9cb5e32b943b1c9ad4555f3163cd 100644 --- a/app/src/main/java/com/huawei/cloudapp/common/CasState.java +++ b/app/src/main/java/com/huawei/cloudapp/common/CasState.java @@ -55,5 +55,6 @@ public class CasState { static public final int CAS_SWITCH_FOREGROUND_SUCCESS = 0x1400; static public final int CAS_EXIT = 0x1700; static public final int CAS_BACK_HOME = 0x1900; + static public final int CAS_OTHERS_CONNECTED = 0x2300; static public final int CAS_INVALID_CMD = 0xFFFF; } diff --git a/app/src/main/java/com/huawei/cloudapp/common/CasUserInfo.java b/app/src/main/java/com/huawei/cloudapp/common/CasUserInfo.java deleted file mode 100644 index 3df3aaf712192df14848f1656d397870e203f8c6..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/huawei/cloudapp/common/CasUserInfo.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2022 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.cloudapp.common; - -import android.os.Parcel; -import android.os.Parcelable; - -public class CasUserInfo implements Parcelable { - public static final String BUNDLE_KEY = "CasUserInfo_Key"; - - /** - * 构造器 - */ - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public CasUserInfo createFromParcel(Parcel in) { - return new CasUserInfo(in); - } - - @Override - public CasUserInfo[] newArray(int size) { - return new CasUserInfo[size]; - } - }; - - - private String mUsername; - private String mUserToken; - private String mUserSessionId; - - public CasUserInfo(String username, String userToken, String userSessionId) { - mUsername = username; - mUserToken = userToken; - mUserSessionId = userSessionId; - } - - protected CasUserInfo(Parcel in) { - mUsername = in.readString(); - mUserToken = in.readString(); - mUserSessionId = in.readString(); - } - - public String getUsername() { - return mUsername; - } - - public String getUserToken() { - return mUserToken; - } - - public String getUserSessionId() { - return mUserSessionId; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) { - parcel.writeString(mUsername); - parcel.writeString(mUserToken); - parcel.writeString(mUserSessionId); - } -} diff --git a/app/src/main/java/com/huawei/cloudapp/model/IConnectInfoModel.java b/app/src/main/java/com/huawei/cloudapp/model/IConnectInfoModel.java new file mode 100644 index 0000000000000000000000000000000000000000..69a3c8908d4629e6599ac41129b36aacc93a467d --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/IConnectInfoModel.java @@ -0,0 +1,14 @@ +package com.huawei.cloudapp.model; + +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.management.CasConnectInfo; + +import java.util.HashMap; +import java.util.List; + +import okhttp3.Response; + +public interface IConnectInfoModel { + void getConnectInfo(User user, String phoneId, String region, final OnRequestListener onRequestListener); + List parseResponseToConnectInfo(Response response) throws Exception; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/IHandleData.java b/app/src/main/java/com/huawei/cloudapp/model/IHandleData.java new file mode 100644 index 0000000000000000000000000000000000000000..fd07ca122fd929336da7fa36a34597ca665e69e8 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/IHandleData.java @@ -0,0 +1,8 @@ +package com.huawei.cloudapp.model; + +import java.util.List; + +public interface IHandleData { + void handleData(List list, int count); + void handleError(Exception e); +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/IPhoneModel.java b/app/src/main/java/com/huawei/cloudapp/model/IPhoneModel.java new file mode 100644 index 0000000000000000000000000000000000000000..3bfd944710e190289f8a3c60afcba760b50c22bb --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/IPhoneModel.java @@ -0,0 +1,16 @@ +package com.huawei.cloudapp.model; + +import com.huawei.cloudapp.model.bean.PhoneInfo; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.PhoneDetail; +import com.huawei.cloudapp.model.bean.direct.PhoneJobResponse; + +import java.util.HashMap; +import java.util.List; + +public interface IPhoneModel { + void getPhoneList(User user, HashMap condition, String region, String projectId, int offset, int limit, final OnRequestListener onRequestListener); + void getPhoneDetailInfo(User user, String region, String projectId, String phoneId, final OnRequestListener onRequestListener); + void resetPhone(User user, String region, String projectId, List phoneIdList, String imageId, List> property, final OnRequestListener onRequestListener); + void restartPhone(User user, String region, String projectId, List phoneIdList, String imageId, List> property, final OnRequestListener onRequestListener); +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/IUserModel.java b/app/src/main/java/com/huawei/cloudapp/model/IUserModel.java new file mode 100644 index 0000000000000000000000000000000000000000..f19d40e366d99a1881bfe7ad6f01287e806a2527 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/IUserModel.java @@ -0,0 +1,13 @@ +package com.huawei.cloudapp.model; + +import com.huawei.cloudapp.model.bean.User; + +import java.util.List; +import java.util.Map; + +import okhttp3.Response; + +public interface IUserModel { + void getUser(User user, String password, String region, final OnRequestListener onRequestListener); + List parseResponseToUser(Response response) throws Exception; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/OnRequestListener.java b/app/src/main/java/com/huawei/cloudapp/model/OnRequestListener.java new file mode 100644 index 0000000000000000000000000000000000000000..d3cc101f0fbec43f7d41415c72720cba0991eb4b --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/OnRequestListener.java @@ -0,0 +1,8 @@ +package com.huawei.cloudapp.model; + +import java.util.List; + +public interface OnRequestListener { + void onSuccess(List t, int count); + void onFailure(Exception e); +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/CustomException.java b/app/src/main/java/com/huawei/cloudapp/model/bean/CustomException.java new file mode 100644 index 0000000000000000000000000000000000000000..b9970a65078cb39036f637a9a23f218522cb24a9 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/CustomException.java @@ -0,0 +1,74 @@ +package com.huawei.cloudapp.model.bean; + +import java.io.IOException; + +public class CustomException extends IOException { + public CustomException() { + super(); + } + public CustomException(String message) { + super(message); + } + + public static class EmptyResponseFromServerException extends CustomException { + } + public static class FailedToLogInException extends CustomException { + } + public static class LogInInfoErrorException extends CustomException { + } + public static class LogInInfoInvalidException extends CustomException { + } + public static class FailedToGetTokenException extends CustomException { + } + public static class FailedToGetPhoneListException extends CustomException { + } + public static class FailedToGetPhoneDetailException extends CustomException { + } + public static class BadRequestException extends CustomException { + } + public static class ForbiddenException extends CustomException { + } + public static class ResourceNotFoundException extends CustomException { + } + public static class ServerError extends CustomException { + } + public static class ServiceUnavailableException extends CustomException { + } + public static class TokenExpireException extends CustomException { + } + public static class NoPermissionException extends CustomException { + } + public static class GetServerListEmptyException extends CustomException { + } + public static class ResponseParamsException extends CustomException { + } + public static class FailedToGetConnectInfoException extends CustomException { + public FailedToGetConnectInfoException() { + super(); + } + public FailedToGetConnectInfoException(String message) { + super(message); + } + } + public static class ConnectInfoErrorException extends CustomException { + } + public static class ParamInvalidException extends CustomException { + } + public static class OpRestrictedException extends CustomException { + } + public static class OpSuspendedException extends CustomException { + } + public static class OpUnverifiedException extends CustomException { + } + public static class PhoneNotFoundException extends CustomException { + } + public static class JobNotFoundException extends CustomException { + } + public static class ServerNotFoundException extends CustomException { + } + public static class UserNotFoundException extends CustomException { + } + public static class DeliverJobFailedException extends CustomException { + } + +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/Phone.java b/app/src/main/java/com/huawei/cloudapp/model/bean/Phone.java new file mode 100644 index 0000000000000000000000000000000000000000..dc28fa8025bf05011b6462f8a0a64c1aeb8c02c3 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/Phone.java @@ -0,0 +1,327 @@ +package com.huawei.cloudapp.model.bean; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; + +public class Phone implements Parcelable { + + @SerializedName("phone_name") + private String phoneName; + @SerializedName("server_id") + private String serverId; + @SerializedName("phone_id") + private String phoneId; + @SerializedName("phone_model_name") + private String phoneModelName; + @SerializedName("image_version") + private String imageVersion; + @SerializedName("image_id") + private String imageId; + @SerializedName("vnc_enable") + private String vncEnable; + @SerializedName("status") + private int status; + @SerializedName("type") + private int type; + @SerializedName("imei") + private String imei; + @SerializedName("availability_zone") + private String availabilityZone; + @SerializedName("traffic_type") + private String trafficType; + @SerializedName("volume_mode") + private int volumeMode; + @SerializedName("metadata") + private Metadata metadata = new Metadata(); + @SerializedName("create_time") + private String createTime; + @SerializedName("update_time") + private String updateTime; + + public String getPhoneName() { + return phoneName; + } + + public void setPhoneName(String phoneName) { + this.phoneName = phoneName; + } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } + + public String getPhoneId() { + return phoneId; + } + + public void setPhoneId(String phoneId) { + this.phoneId = phoneId; + } + + public String getPhoneModelName() { + return phoneModelName; + } + + public void setPhoneModelName(String phoneModelName) { + this.phoneModelName = phoneModelName; + } + + public String getImageVersion() { + return imageVersion; + } + + public void setImageVersion(String imageVersion) { + this.imageVersion = imageVersion; + } + + public String getImageId() { + return imageId; + } + + public void setImageId(String imageId) { + this.imageId = imageId; + } + + public String getVncEnable() { + return vncEnable; + } + + public void setVncEnable(String vncEnable) { + this.vncEnable = vncEnable; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getImei() { + return imei; + } + + public void setImei(String imei) { + this.imei = imei; + } + + public String getAvailabilityZone() { + return availabilityZone; + } + + public void setAvailabilityZone(String availabilityZone) { + this.availabilityZone = availabilityZone; + } + + public String getTrafficType() { + return trafficType; + } + + public void setTrafficType(String trafficType) { + this.trafficType = trafficType; + } + + public int getVolumeMode() { + return volumeMode; + } + + public void setVolumeMode(int volumeMode) { + this.volumeMode = volumeMode; + } + + public Metadata getMetadata() { + return metadata; + } + + public void setMetadata(Metadata metadata) { + this.metadata = metadata; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + public static class Metadata implements Parcelable { + @SerializedName("order_id") + private String orderId; + @SerializedName("product_id") + private String productId; + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.orderId); + dest.writeString(this.productId); + } + + public void readFromParcel(Parcel source) { + this.orderId = source.readString(); + this.productId = source.readString(); + } + + public Metadata() { + } + + protected Metadata(Parcel in) { + this.orderId = in.readString(); + this.productId = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Metadata createFromParcel(Parcel source) { + return new Metadata(source); + } + + @Override + public Metadata[] newArray(int size) { + return new Metadata[size]; + } + }; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.phoneName); + dest.writeString(this.serverId); + dest.writeString(this.phoneId); + dest.writeString(this.phoneModelName); + dest.writeString(this.imageVersion); + dest.writeString(this.imageId); + dest.writeString(this.vncEnable); + dest.writeInt(this.status); + dest.writeInt(this.type); + dest.writeString(this.imei); + dest.writeString(this.availabilityZone); + dest.writeString(this.trafficType); + dest.writeInt(this.volumeMode); + dest.writeParcelable(this.metadata, flags); + dest.writeString(this.createTime); + dest.writeString(this.updateTime); + } + + public void readFromParcel(Parcel source) { + this.phoneName = source.readString(); + this.serverId = source.readString(); + this.phoneId = source.readString(); + this.phoneModelName = source.readString(); + this.imageVersion = source.readString(); + this.imageId = source.readString(); + this.vncEnable = source.readString(); + this.status = source.readInt(); + this.type = source.readInt(); + this.imei = source.readString(); + this.availabilityZone = source.readString(); + this.trafficType = source.readString(); + this.volumeMode = source.readInt(); + this.metadata = source.readParcelable(Metadata.class.getClassLoader()); + this.createTime = source.readString(); + this.updateTime = source.readString(); + } + + public Phone() { + } + + public Phone(String phoneName, String phoneId) { + this.phoneName = phoneName; + this.serverId = null; + this.phoneId = phoneId; + this.phoneModelName = null; + this.imageVersion = null; + this.imageId = null; + this.vncEnable = null; + this.status = 0; + this.type = 0; + this.imei = null; + this.availabilityZone = null; + this.trafficType = null; + this.volumeMode = 0; + this.metadata = null; + this.createTime = null; + this.updateTime = null; + } + + protected Phone(Parcel in) { + this.phoneName = in.readString(); + this.serverId = in.readString(); + this.phoneId = in.readString(); + this.phoneModelName = in.readString(); + this.imageVersion = in.readString(); + this.imageId = in.readString(); + this.vncEnable = in.readString(); + this.status = in.readInt(); + this.type = in.readInt(); + this.imei = in.readString(); + this.availabilityZone = in.readString(); + this.trafficType = in.readString(); + this.volumeMode = in.readInt(); + this.metadata = in.readParcelable(Metadata.class.getClassLoader()); + this.createTime = in.readString(); + this.updateTime = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Phone createFromParcel(Parcel source) { + return new Phone(source); + } + + @Override + public Phone[] newArray(int size) { + return new Phone[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/PhoneCardItem.java b/app/src/main/java/com/huawei/cloudapp/model/bean/PhoneInfo.java similarity index 53% rename from app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/PhoneCardItem.java rename to app/src/main/java/com/huawei/cloudapp/model/bean/PhoneInfo.java index 49011d0fc194bbeef98b409a109b3c97ab2d5cc7..d48aedca085406b39ce36d223116ef9ce25c7f19 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/PhoneCardItem.java +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/PhoneInfo.java @@ -14,22 +14,42 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui.surface.viewpagecards; +package com.huawei.cloudapp.model.bean; -public class PhoneCardItem { +import android.widget.TextView; +import androidx.annotation.NonNull; + +import com.huawei.cloudapp.R; + +public class PhoneInfo { + + private Phone mPhone; private String mPhoneInfo; - private String mPhoneName; - private String mPhoneId; private String mPhoneRegion; + private int itemPosition = 0; + private boolean checked = false; + + public PhoneInfo(String name, String info, String id, String region) { + mPhone = new Phone(name, id); + mPhoneInfo = info; + mPhoneRegion = region; + } - public PhoneCardItem(String name, String info, String id, String region) { - mPhoneName = name; + public PhoneInfo(Phone phone, String info, String region) { + mPhone = phone; mPhoneInfo = info; - mPhoneId = id; mPhoneRegion = region; } + public Phone getPhone() { + return mPhone; + } + + public void setPhone(Phone phone) { + mPhone = phone; + } + public String getInfo() { return mPhoneInfo; } @@ -38,16 +58,19 @@ public class PhoneCardItem { mPhoneInfo = info; } + public void setPhoneName(String mPhoneName) { + this.mPhone.setPhoneName(mPhoneName); + } public String getName() { - return mPhoneName; + return mPhone.getPhoneName(); } public String getPhoneId() { - return mPhoneId; + return mPhone.getPhoneId(); } public void setPhoneId(String mPhoneId) { - this.mPhoneId = mPhoneId; + this.mPhone.setPhoneId(mPhoneId); } public String getRegion() { @@ -57,4 +80,12 @@ public class PhoneCardItem { public void setRegion(String mPhoneRegion) { this.mPhoneRegion = mPhoneRegion; } + + public boolean isChecked() { + return checked; + } + + public void setChecked(boolean checked) { + this.checked = checked; + } } diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/User.java b/app/src/main/java/com/huawei/cloudapp/model/bean/User.java new file mode 100644 index 0000000000000000000000000000000000000000..430f19b081ef06a019584ff85df97bd663dbb663 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/User.java @@ -0,0 +1,154 @@ +/* + * Copyright 2022 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.cloudapp.model.bean; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.HashMap; +public class User implements Parcelable { + public static final String BUNDLE_KEY = "CasUserInfo_Key"; + + private String mUsername; + private String mIamUsername; + private HashMap mUserToken; + private HashMap mUserTokenExpireTime; + private HashMap mUserProjectId; + private String mUserSessionId; + + public User(String username, String iamUsername, + HashMap userToken, + HashMap userTokenExpireTime, + HashMap userProjectId, + String userSessionId) { + mUsername = username; + mIamUsername = iamUsername; + + if (userToken != null) { + mUserToken = userToken; + } else { + mUserToken = new HashMap<>(); + } + + if (userTokenExpireTime != null) { + mUserTokenExpireTime = userTokenExpireTime; + } else { + mUserTokenExpireTime = new HashMap<>(); + } + + if (userProjectId != null) { + mUserProjectId = userProjectId; + } else { + mUserProjectId = new HashMap<>(); + } + mUserSessionId = userSessionId; + } + + + public String getUsername() { + return mUsername; + } + + public String getIamUsername() { + return mIamUsername; + } + + public void setUserToken(HashMap mUserToken) { + this.mUserToken = mUserToken; + } + + public void setUserTokenExpireTime(HashMap mUserTokenExpireTime) { + this.mUserTokenExpireTime = mUserTokenExpireTime; + } + + public void setUserSessionId(String mUserSessionId) { + this.mUserSessionId = mUserSessionId; + } + + public String getUserTokenByRegion(String region) { + return mUserToken.get(region); + } + + public String getUserTokenExpireTimeByRegion(String region) { + return mUserTokenExpireTime.get(region); + } + + public HashMap getUserToken() { + return mUserToken; + } + + public HashMap getUserTokenExpireTime() { + return mUserTokenExpireTime; + } + + public String getUserSessionId() { + return mUserSessionId; + } + + public HashMap getUserProjectId() { + return mUserProjectId; + } + + public void setUserProjectId(HashMap mUserProjectId) { + this.mUserProjectId = mUserProjectId; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.mUsername); + dest.writeString(this.mIamUsername); + dest.writeSerializable(this.mUserToken); + dest.writeSerializable(this.mUserTokenExpireTime); + dest.writeSerializable(this.mUserProjectId); + dest.writeString(this.mUserSessionId); + } + + public void readFromParcel(Parcel source) { + this.mUsername = source.readString(); + this.mIamUsername = source.readString(); + this.mUserToken = (HashMap) source.readSerializable(); + this.mUserTokenExpireTime = (HashMap) source.readSerializable(); + this.mUserProjectId = (HashMap) source.readSerializable(); + this.mUserSessionId = source.readString(); + } + + protected User(Parcel in) { + this.mUsername = in.readString(); + this.mIamUsername = in.readString(); + this.mUserToken = (HashMap) in.readSerializable(); + this.mUserTokenExpireTime = (HashMap) in.readSerializable(); + this.mUserProjectId = (HashMap) in.readSerializable(); + this.mUserSessionId = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public User createFromParcel(Parcel source) { + return new User(source); + } + + @Override + public User[] newArray(int size) { + return new User[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/CPHError.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/CPHError.java new file mode 100644 index 0000000000000000000000000000000000000000..a7fb4a34a84709002124bed2d6aab8b5a987aee8 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/CPHError.java @@ -0,0 +1,79 @@ +package com.huawei.cloudapp.model.bean.direct; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; + +public class CPHError implements Parcelable { + + @SerializedName("error_msg") + private String errorMsg; + @SerializedName("error_code") + private String errorCode; + @SerializedName("request_id") + private String requestId; + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.errorMsg); + dest.writeString(this.errorCode); + dest.writeString(this.requestId); + } + + public void readFromParcel(Parcel source) { + this.errorMsg = source.readString(); + this.errorCode = source.readString(); + this.requestId = source.readString(); + } + + public CPHError() { + } + + protected CPHError(Parcel in) { + this.errorMsg = in.readString(); + this.errorCode = in.readString(); + this.requestId = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public CPHError createFromParcel(Parcel source) { + return new CPHError(source); + } + + @Override + public CPHError[] newArray(int size) { + return new CPHError[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/ConnectInfos.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/ConnectInfos.java new file mode 100644 index 0000000000000000000000000000000000000000..1aa47fc455d8ae6da6483fdf5de7249719983abf --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/ConnectInfos.java @@ -0,0 +1,351 @@ +package com.huawei.cloudapp.model.bean.direct; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class ConnectInfos implements Parcelable { + + @SerializedName("request_id") + private String requestId; + @SerializedName("connect_infos") + private List connectInfos; + @SerializedName("errors") + private List errors; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public List getConnectInfos() { + return connectInfos; + } + + public void setConnectInfos(List connectInfos) { + this.connectInfos = connectInfos; + } + + public List getErrors() { + return errors; + } + + public void setErrors(List errors) { + this.errors = errors; + } + + public static class ConnectInfo implements Parcelable { + @SerializedName("phone_id") + private String phoneId; + @SerializedName("access_info") + public AccessInfo accessInfo; + + public String getPhoneId() { + return phoneId; + } + + public void setPhoneId(String phoneId) { + this.phoneId = phoneId; + } + + public AccessInfo getAccessInfo() { + return accessInfo; + } + + public void setAccessInfo(AccessInfo accessInfo) { + this.accessInfo = accessInfo; + } + + public static class AccessInfo implements Parcelable { + @SerializedName("access_ip") + private String accessIp; + @SerializedName("intranet_ip") + private String intranetIp; + @SerializedName("access_ipv6") + private String accessIpv6; + @SerializedName("access_port") + private int accessPort; + @SerializedName("session_id") + private String sessionId; + @SerializedName("timestamp") + private String timestamp; + @SerializedName("ticket") + private String ticket; + + public String getAccessIp() { + return accessIp; + } + + public void setAccessIp(String accessIp) { + this.accessIp = accessIp; + } + + public String getIntranetIp() { + return intranetIp; + } + + public void setIntranetIp(String intranetIp) { + this.intranetIp = intranetIp; + } + + public String getAccessIpv6() { + return accessIpv6; + } + + public void setAccessIpv6(String accessIpv6) { + this.accessIpv6 = accessIpv6; + } + + public int getAccessPort() { + return accessPort; + } + + public void setAccessPort(int accessPort) { + this.accessPort = accessPort; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + public String getTicket() { + return ticket; + } + + public void setTicket(String ticket) { + this.ticket = ticket; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.accessIp); + dest.writeString(this.intranetIp); + dest.writeString(this.accessIpv6); + dest.writeInt(this.accessPort); + dest.writeString(this.sessionId); + dest.writeString(this.timestamp); + dest.writeString(this.ticket); + } + + public void readFromParcel(Parcel source) { + this.accessIp = source.readString(); + this.intranetIp = source.readString(); + this.accessIpv6 = source.readString(); + this.accessPort = source.readInt(); + this.sessionId = source.readString(); + this.timestamp = source.readString(); + this.ticket = source.readString(); + } + + public AccessInfo() { + } + + protected AccessInfo(Parcel in) { + this.accessIp = in.readString(); + this.intranetIp = in.readString(); + this.accessIpv6 = in.readString(); + this.accessPort = in.readInt(); + this.sessionId = in.readString(); + this.timestamp = in.readString(); + this.ticket = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public AccessInfo createFromParcel(Parcel source) { + return new AccessInfo(source); + } + + @Override + public AccessInfo[] newArray(int size) { + return new AccessInfo[size]; + } + }; + + @Override + public String toString() { + return "AccessInfo{" + + "accessIp='" + accessIp + '\'' + + ", intranetIp='" + intranetIp + '\'' + + ", accessIpv6='" + accessIpv6 + '\'' + + ", accessPort=" + accessPort + + ", sessionId='" + sessionId + '\'' + + ", timestamp='" + timestamp + '\'' + + ", ticket='" + ticket + '\'' + + '}'; + } + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.phoneId); + dest.writeParcelable(this.accessInfo, flags); + } + + public void readFromParcel(Parcel source) { + this.phoneId = source.readString(); + this.accessInfo = source.readParcelable(AccessInfo.class.getClassLoader()); + } + + public ConnectInfo() { + } + + protected ConnectInfo(Parcel in) { + this.phoneId = in.readString(); + this.accessInfo = in.readParcelable(AccessInfo.class.getClassLoader()); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public ConnectInfo createFromParcel(Parcel source) { + return new ConnectInfo(source); + } + + @Override + public ConnectInfo[] newArray(int size) { + return new ConnectInfo[size]; + } + }; + } + + public static class Errors implements Parcelable { + @SerializedName("phone_id") + private String phoneId; + @SerializedName("error_code") + private String errorCode; + @SerializedName("error_msg") + private String errorMsg; + + public String getPhoneId() { + return phoneId; + } + + public void setPhoneId(String phoneId) { + this.phoneId = phoneId; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.phoneId); + dest.writeString(this.errorCode); + dest.writeString(this.errorMsg); + } + + public void readFromParcel(Parcel source) { + this.phoneId = source.readString(); + this.errorCode = source.readString(); + this.errorMsg = source.readString(); + } + + public Errors() { + } + + protected Errors(Parcel in) { + this.phoneId = in.readString(); + this.errorCode = in.readString(); + this.errorMsg = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Errors createFromParcel(Parcel source) { + return new Errors(source); + } + + @Override + public Errors[] newArray(int size) { + return new Errors[size]; + } + }; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.requestId); + dest.writeTypedList(this.connectInfos); + dest.writeTypedList(this.errors); + } + + public void readFromParcel(Parcel source) { + this.requestId = source.readString(); + this.connectInfos = source.createTypedArrayList(ConnectInfos.ConnectInfo.CREATOR); + this.errors = source.createTypedArrayList(Errors.CREATOR); + } + + public ConnectInfos() { + } + + protected ConnectInfos(Parcel in) { + this.requestId = in.readString(); + this.connectInfos = in.createTypedArrayList(ConnectInfos.ConnectInfo.CREATOR); + this.errors = in.createTypedArrayList(Errors.CREATOR); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public ConnectInfos createFromParcel(Parcel source) { + return new ConnectInfos(source); + } + + @Override + public ConnectInfos[] newArray(int size) { + return new ConnectInfos[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneDetail.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneDetail.java new file mode 100644 index 0000000000000000000000000000000000000000..f1eea19b602860cc40009fb945f0b5d216040f90 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneDetail.java @@ -0,0 +1,325 @@ +package com.huawei.cloudapp.model.bean.direct; + +import com.google.gson.annotations.SerializedName; +import com.huawei.cloudapp.model.bean.Phone; + +import java.util.List; + +public class PhoneDetail { + @SerializedName("request_id") + private String requestId; + @SerializedName("phone_name") + private String phoneName; + @SerializedName("server_id") + private String serverId; + @SerializedName("phone_id") + private String phoneId; + @SerializedName("image_id") + private String imageId; + @SerializedName("phone_model_name") + private String phoneModelName; + @SerializedName("image_version") + private String imageVersion; + @SerializedName("status") + private int status; + @SerializedName("imei") + private long imei; + @SerializedName("availability_zone") + private String availabilityZone; + @SerializedName("traffic_type") + private String trafficType; + @SerializedName("volume_mode") + private int volumeMode; + @SerializedName("phone_data_volume") + private PhoneDataVolume phoneDataVolume; + @SerializedName("property") + private String property; + @SerializedName("metadata") + private Phone.Metadata metadata; + @SerializedName("create_time") + private String createTime; + @SerializedName("update_time") + private String updateTime; + @SerializedName("access_infos") + private List accessInfos; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getPhoneName() { + return phoneName; + } + + public void setPhoneName(String phoneName) { + this.phoneName = phoneName; + } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } + + public String getPhoneId() { + return phoneId; + } + + public void setPhoneId(String phoneId) { + this.phoneId = phoneId; + } + + public String getImageId() { + return imageId; + } + + public void setImageId(String imageId) { + this.imageId = imageId; + } + + public String getPhoneModelName() { + return phoneModelName; + } + + public void setPhoneModelName(String phoneModelName) { + this.phoneModelName = phoneModelName; + } + + public String getImageVersion() { + return imageVersion; + } + + public void setImageVersion(String imageVersion) { + this.imageVersion = imageVersion; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public long getImei() { + return imei; + } + + public void setImei(long imei) { + this.imei = imei; + } + + public String getAvailabilityZone() { + return availabilityZone; + } + + public void setAvailabilityZone(String availabilityZone) { + this.availabilityZone = availabilityZone; + } + + public String getTrafficType() { + return trafficType; + } + + public void setTrafficType(String trafficType) { + this.trafficType = trafficType; + } + + public int getVolumeMode() { + return volumeMode; + } + + public void setVolumeMode(int volumeMode) { + this.volumeMode = volumeMode; + } + + public PhoneDataVolume getPhoneDataVolume() { + return phoneDataVolume; + } + + public void setPhoneDataVolume(PhoneDataVolume phoneDataVolume) { + this.phoneDataVolume = phoneDataVolume; + } + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + + public Phone.Metadata getMetadata() { + return metadata; + } + + public void setMetadata(Phone.Metadata metadata) { + this.metadata = metadata; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + public List getAccessInfos() { + return accessInfos; + } + + public void setAccessInfos(List accessInfos) { + this.accessInfos = accessInfos; + } + + public static class PhoneDataVolume { + @SerializedName("volume_type") + private String volumeType; + @SerializedName("volume_size") + private int volumeSize; + + public String getVolumeType() { + return volumeType; + } + + public void setVolumeType(String volumeType) { + this.volumeType = volumeType; + } + + public int getVolumeSize() { + return volumeSize; + } + + public void setVolumeSize(int volumeSize) { + this.volumeSize = volumeSize; + } + } + + public static class AccessInfo { + @SerializedName("type") + private String type; + @SerializedName("device_ip") + private String deviceIp; + @SerializedName("phone_ip") + private String phoneIp; + @SerializedName("listen_port") + private int listenPort; + @SerializedName("access_ip") + private String accessIp; + @SerializedName("public_ip") + private String publicIp; + @SerializedName("intranet_ip") + private String intranetIp; + @SerializedName("server_ip") + private String serverIp; + @SerializedName("access_port") + private int accessPort; + @SerializedName("phone_ipv6") + private String phoneIpv6; + @SerializedName("server_ipv6") + private String serverIpv6; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDeviceIp() { + return deviceIp; + } + + public void setDeviceIp(String deviceIp) { + this.deviceIp = deviceIp; + } + + public String getPhoneIp() { + return phoneIp; + } + + public void setPhoneIp(String phoneIp) { + this.phoneIp = phoneIp; + } + + public int getListenPort() { + return listenPort; + } + + public void setListenPort(int listenPort) { + this.listenPort = listenPort; + } + + public String getAccessIp() { + return accessIp; + } + + public void setAccessIp(String accessIp) { + this.accessIp = accessIp; + } + + public String getPublicIp() { + return publicIp; + } + + public void setPublicIp(String publicIp) { + this.publicIp = publicIp; + } + + public String getIntranetIp() { + return intranetIp; + } + + public void setIntranetIp(String intranetIp) { + this.intranetIp = intranetIp; + } + + public String getServerIp() { + return serverIp; + } + + public void setServerIp(String serverIp) { + this.serverIp = serverIp; + } + + public int getAccessPort() { + return accessPort; + } + + public void setAccessPort(int accessPort) { + this.accessPort = accessPort; + } + + public String getPhoneIpv6() { + return phoneIpv6; + } + + public void setPhoneIpv6(String phoneIpv6) { + this.phoneIpv6 = phoneIpv6; + } + + public String getServerIpv6() { + return serverIpv6; + } + + public void setServerIpv6(String serverIpv6) { + this.serverIpv6 = serverIpv6; + } + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneJobRequest.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneJobRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..4afa2cab4ddcdfcacd569af32b7adf42d6fe3d7c --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneJobRequest.java @@ -0,0 +1,130 @@ +package com.huawei.cloudapp.model.bean.direct; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; +import java.util.List; + +public class PhoneJobRequest implements Parcelable { + + @SerializedName("image_id") + private String imageId; + @SerializedName("phones") + private List phones = new ArrayList<>(); + + public String getImageId() { + return imageId; + } + + public void setImageId(String imageId) { + this.imageId = imageId; + } + + public List getPhones() { + return phones; + } + + public void setPhones(List phones) { + this.phones = phones; + } + + public static class PhoneProperty implements Parcelable { + @SerializedName("phone_id") + private String mPhoneId; + @SerializedName("property") + private String mProperty; + + public PhoneProperty(String phoneId, String property) { + mPhoneId = phoneId; + mProperty = property; + } + + public String getPhoneId() { + return mPhoneId; + } + + public void setPhoneId(String mPhoneId) { + this.mPhoneId = mPhoneId; + } + + public String getProperty() { + return mProperty; + } + + public void setProperty(String mProperty) { + this.mProperty = mProperty; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.mPhoneId); + dest.writeString(this.mProperty); + } + + public void readFromParcel(Parcel source) { + this.mPhoneId = source.readString(); + this.mProperty = source.readString(); + } + + protected PhoneProperty(Parcel in) { + this.mPhoneId = in.readString(); + this.mProperty = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public PhoneProperty createFromParcel(Parcel source) { + return new PhoneProperty(source); + } + + @Override + public PhoneProperty[] newArray(int size) { + return new PhoneProperty[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.imageId); + dest.writeTypedList(this.phones); + } + + public void readFromParcel(Parcel source) { + this.imageId = source.readString(); + this.phones = source.createTypedArrayList(PhoneProperty.CREATOR); + } + + public PhoneJobRequest() { + } + + protected PhoneJobRequest(Parcel in) { + this.imageId = in.readString(); + this.phones = in.createTypedArrayList(PhoneProperty.CREATOR); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public PhoneJobRequest createFromParcel(Parcel source) { + return new PhoneJobRequest(source); + } + + @Override + public PhoneJobRequest[] newArray(int size) { + return new PhoneJobRequest[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneJobResponse.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneJobResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..7ae10ecdaf381e7bd6d3700a04bfc225366b7517 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneJobResponse.java @@ -0,0 +1,73 @@ +package com.huawei.cloudapp.model.bean.direct; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class PhoneJobResponse { + + + @SerializedName("request_id") + private String requestId; + @SerializedName("jobs") + private List jobs; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public List getJobs() { + return jobs; + } + + public void setJobs(List jobs) { + this.jobs = jobs; + } + + public static class Jobs { + @SerializedName("phone_id") + private String phoneId; + @SerializedName("job_id") + private String jobId; + @SerializedName("error_code") + private String errorCode; + @SerializedName("error_msg") + private String errorMsg; + + public String getPhoneId() { + return phoneId; + } + + public void setPhoneId(String phoneId) { + this.phoneId = phoneId; + } + + public String getJobId() { + return jobId; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneList.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneList.java new file mode 100644 index 0000000000000000000000000000000000000000..100b7e461596df0019194f992112024ccb0b1674 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/PhoneList.java @@ -0,0 +1,84 @@ +package com.huawei.cloudapp.model.bean.direct; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; +import com.huawei.cloudapp.model.bean.Phone; + +import java.util.ArrayList; +import java.util.List; + +public class PhoneList implements Parcelable { + + @SerializedName("request_id") + private String requestId; + @SerializedName("count") + private int count; + @SerializedName("phones") + private List phones = new ArrayList<>(); + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public List getPhones() { + return phones; + } + + public void setPhones(List phones) { + this.phones = phones; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.requestId); + dest.writeInt(this.count); + dest.writeTypedList(this.phones); + } + + public void readFromParcel(Parcel source) { + this.requestId = source.readString(); + this.count = source.readInt(); + this.phones = source.createTypedArrayList(Phone.CREATOR); + } + + public PhoneList() { + } + + protected PhoneList(Parcel in) { + this.requestId = in.readString(); + this.count = in.readInt(); + this.phones = in.createTypedArrayList(Phone.CREATOR); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public PhoneList createFromParcel(Parcel source) { + return new PhoneList(source); + } + + @Override + public PhoneList[] newArray(int size) { + return new PhoneList[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/ServerList.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/ServerList.java new file mode 100644 index 0000000000000000000000000000000000000000..de0df06c694036927d241e12d028129e5b1810a0 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/ServerList.java @@ -0,0 +1,460 @@ +package com.huawei.cloudapp.model.bean.direct; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; +import java.util.List; + +public class ServerList { + + @SerializedName("request_id") + private String requestId; + @SerializedName("count") + private int count; + @SerializedName("servers") + private List servers; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public List getServers() { + return servers; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public class Server implements Parcelable { + + public static final String BUNDLE_KEY = "Server_Key"; + + @SerializedName("server_name") + private String serverName; + @SerializedName("server_id") + private String serverId; + @SerializedName("server_model_name") + private String serverModelName; + @SerializedName("phone_model_name") + private String phoneModelName; + @SerializedName("keypair_name") + private String keypairName; + @SerializedName("status") + private int status; + @SerializedName("vpc_id") + private String vpcId; + @SerializedName("cidr") + private String cidr; + @SerializedName("vpc_cidr") + private String vpcCidr; + @SerializedName("subnet_id") + private String subnetId; + @SerializedName("subnet_cidr") + private String subnetCidr; + @SerializedName("resource_project_id") + private String resourceProjectId; + @SerializedName("metadata") + private Metadata metadata = new Metadata(); + @SerializedName("availability_zone") + private String availabilityZone; + @SerializedName("network_version") + private String networkVersion; + @SerializedName("create_time") + private String createTime; + @SerializedName("update_time") + private String updateTime; + @SerializedName("addresses") + private List addresses; + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public String getServerId() { + return serverId; + } + + public void setServerId(String serverId) { + this.serverId = serverId; + } + + public String getServerModelName() { + return serverModelName; + } + + public void setServerModelName(String serverModelName) { + this.serverModelName = serverModelName; + } + + public String getPhoneModelName() { + return phoneModelName; + } + + public void setPhoneModelName(String phoneModelName) { + this.phoneModelName = phoneModelName; + } + + public String getKeypairName() { + return keypairName; + } + + public void setKeypairName(String keypairName) { + this.keypairName = keypairName; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getVpcId() { + return vpcId; + } + + public void setVpcId(String vpcId) { + this.vpcId = vpcId; + } + + public String getCidr() { + return cidr; + } + + public void setCidr(String cidr) { + this.cidr = cidr; + } + + public String getVpcCidr() { + return vpcCidr; + } + + public void setVpcCidr(String vpcCidr) { + this.vpcCidr = vpcCidr; + } + + public String getSubnetId() { + return subnetId; + } + + public void setSubnetId(String subnetId) { + this.subnetId = subnetId; + } + + public String getSubnetCidr() { + return subnetCidr; + } + + public void setSubnetCidr(String subnetCidr) { + this.subnetCidr = subnetCidr; + } + + public String getResourceProjectId() { + return resourceProjectId; + } + + public void setResourceProjectId(String resourceProjectId) { + this.resourceProjectId = resourceProjectId; + } + + public Metadata getMetadata() { + return metadata; + } + + public void setMetadata(Metadata metadata) { + this.metadata = metadata; + } + + public String getAvailabilityZone() { + return availabilityZone; + } + + public void setAvailabilityZone(String availabilityZone) { + this.availabilityZone = availabilityZone; + } + + public String getNetworkVersion() { + return networkVersion; + } + + public void setNetworkVersion(String networkVersion) { + this.networkVersion = networkVersion; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + public List getAddresses() { + return addresses; + } + + public void setAddresses(List addresses) { + this.addresses = addresses; + } + + public class Metadata implements Parcelable { + @SerializedName("product_id") + private String productId; + @SerializedName("order_id") + private String orderId; + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.productId); + dest.writeString(this.orderId); + } + + public void readFromParcel(Parcel source) { + this.productId = source.readString(); + this.orderId = source.readString(); + } + + public Metadata() { + } + + protected Metadata(Parcel in) { + this.productId = in.readString(); + this.orderId = in.readString(); + } + + public final Creator CREATOR = new Creator() { + @Override + public Metadata createFromParcel(Parcel source) { + return new Metadata(source); + } + + @Override + public Metadata[] newArray(int size) { + return new Metadata[size]; + } + }; + } + + public class Addresses implements Parcelable { + @SerializedName("intranet_ip") + private String intranetIp; + @SerializedName("server_ip") + private String serverIp; + @SerializedName("access_ip") + private String accessIp; + @SerializedName("public_ip") + private String publicIp; + + public String getIntranetIp() { + return intranetIp; + } + + public void setIntranetIp(String intranetIp) { + this.intranetIp = intranetIp; + } + + public String getServerIp() { + return serverIp; + } + + public void setServerIp(String serverIp) { + this.serverIp = serverIp; + } + + public String getAccessIp() { + return accessIp; + } + + public void setAccessIp(String accessIp) { + this.accessIp = accessIp; + } + + public String getPublicIp() { + return publicIp; + } + + public void setPublicIp(String publicIp) { + this.publicIp = publicIp; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.intranetIp); + dest.writeString(this.serverIp); + dest.writeString(this.accessIp); + dest.writeString(this.publicIp); + } + + public void readFromParcel(Parcel source) { + this.intranetIp = source.readString(); + this.serverIp = source.readString(); + this.accessIp = source.readString(); + this.publicIp = source.readString(); + } + + public Addresses() { + } + + protected Addresses(Parcel in) { + this.intranetIp = in.readString(); + this.serverIp = in.readString(); + this.accessIp = in.readString(); + this.publicIp = in.readString(); + } + + public final Creator CREATOR = new Creator() { + @Override + public Addresses createFromParcel(Parcel source) { + return new Addresses(source); + } + + @Override + public Addresses[] newArray(int size) { + return new Addresses[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.serverName); + dest.writeString(this.serverId); + dest.writeString(this.serverModelName); + dest.writeString(this.phoneModelName); + dest.writeString(this.keypairName); + dest.writeInt(this.status); + dest.writeString(this.vpcId); + dest.writeString(this.cidr); + dest.writeString(this.vpcCidr); + dest.writeString(this.subnetId); + dest.writeString(this.subnetCidr); + dest.writeString(this.resourceProjectId); + dest.writeParcelable(this.metadata, flags); + dest.writeString(this.availabilityZone); + dest.writeString(this.networkVersion); + dest.writeString(this.createTime); + dest.writeString(this.updateTime); + dest.writeList(this.addresses); + } + + public void readFromParcel(Parcel source) { + this.serverName = source.readString(); + this.serverId = source.readString(); + this.serverModelName = source.readString(); + this.phoneModelName = source.readString(); + this.keypairName = source.readString(); + this.status = source.readInt(); + this.vpcId = source.readString(); + this.cidr = source.readString(); + this.vpcCidr = source.readString(); + this.subnetId = source.readString(); + this.subnetCidr = source.readString(); + this.resourceProjectId = source.readString(); + this.metadata = source.readParcelable(Metadata.class.getClassLoader()); + this.availabilityZone = source.readString(); + this.networkVersion = source.readString(); + this.createTime = source.readString(); + this.updateTime = source.readString(); + this.addresses = new ArrayList(); + source.readList(this.addresses, Addresses.class.getClassLoader()); + } + + public Server() { + } + + protected Server(Parcel in) { + this.serverName = in.readString(); + this.serverId = in.readString(); + this.serverModelName = in.readString(); + this.phoneModelName = in.readString(); + this.keypairName = in.readString(); + this.status = in.readInt(); + this.vpcId = in.readString(); + this.cidr = in.readString(); + this.vpcCidr = in.readString(); + this.subnetId = in.readString(); + this.subnetCidr = in.readString(); + this.resourceProjectId = in.readString(); + this.metadata = in.readParcelable(Metadata.class.getClassLoader()); + this.availabilityZone = in.readString(); + this.networkVersion = in.readString(); + this.createTime = in.readString(); + this.updateTime = in.readString(); + this.addresses = new ArrayList(); + in.readList(this.addresses, Addresses.class.getClassLoader()); + } + + public final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Server createFromParcel(Parcel source) { + return new Server(source); + } + + @Override + public Server[] newArray(int size) { + return new Server[size]; + } + }; + } + +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/bean/direct/UserToken.java b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/UserToken.java new file mode 100644 index 0000000000000000000000000000000000000000..631c93e52bc076f539da3662e9c94b7526d4a27f --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/direct/UserToken.java @@ -0,0 +1,447 @@ +package com.huawei.cloudapp.model.bean.direct; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; +import java.util.List; + +public class UserToken implements Parcelable { + + @SerializedName("auth") + private AuthDTO auth = new AuthDTO(); + + public AuthDTO getAuth() { + return auth; + } + + public void setAuth(AuthDTO auth) { + this.auth = auth; + } + + public static class AuthDTO implements Parcelable { + @SerializedName("identity") + private IdentityDTO identity = new IdentityDTO(); + @SerializedName("scope") + private ScopeDTO scope = new ScopeDTO(); + + public IdentityDTO getIdentity() { + return identity; + } + + public void setIdentity(IdentityDTO identity) { + this.identity = identity; + } + + public ScopeDTO getScope() { + return scope; + } + + public void setScope(ScopeDTO scope) { + this.scope = scope; + } + + public static class IdentityDTO implements Parcelable { + @SerializedName("password") + private PasswordDTO password = new PasswordDTO(); + @SerializedName("methods") + private List methods = new ArrayList<>(); + + public PasswordDTO getPassword() { + return password; + } + + public void setPassword(PasswordDTO password) { + this.password = password; + } + + public List getMethods() { + return methods; + } + + public void setMethods(List methods) { + this.methods = methods; + } + + public static class PasswordDTO implements Parcelable { + @SerializedName("user") + private UserDTO user = new UserDTO(); + + public UserDTO getUser() { + return user; + } + + public void setUser(UserDTO user) { + this.user = user; + } + + public static class UserDTO implements Parcelable { + @SerializedName("domain") + private DomainDTO domain = new DomainDTO(); + @SerializedName("name") + private String name; + @SerializedName("password") + private String password; + + public DomainDTO getDomain() { + return domain; + } + + public void setDomain(DomainDTO domain) { + this.domain = domain; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public static class DomainDTO implements Parcelable { + @SerializedName("name") + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.name); + } + + public void readFromParcel(Parcel source) { + this.name = source.readString(); + } + + public DomainDTO() { + } + + protected DomainDTO(Parcel in) { + this.name = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public DomainDTO createFromParcel(Parcel source) { + return new DomainDTO(source); + } + + @Override + public DomainDTO[] newArray(int size) { + return new DomainDTO[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.domain, flags); + dest.writeString(this.name); + dest.writeString(this.password); + } + + public void readFromParcel(Parcel source) { + this.domain = source.readParcelable(DomainDTO.class.getClassLoader()); + this.name = source.readString(); + this.password = source.readString(); + } + + public UserDTO() { + } + + protected UserDTO(Parcel in) { + this.domain = in.readParcelable(DomainDTO.class.getClassLoader()); + this.name = in.readString(); + this.password = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public UserDTO createFromParcel(Parcel source) { + return new UserDTO(source); + } + + @Override + public UserDTO[] newArray(int size) { + return new UserDTO[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.user, flags); + } + + public void readFromParcel(Parcel source) { + this.user = source.readParcelable(UserDTO.class.getClassLoader()); + } + + public PasswordDTO() { + } + + protected PasswordDTO(Parcel in) { + this.user = in.readParcelable(UserDTO.class.getClassLoader()); + } + + public static final Creator CREATOR = new Creator() { + @Override + public PasswordDTO createFromParcel(Parcel source) { + return new PasswordDTO(source); + } + + @Override + public PasswordDTO[] newArray(int size) { + return new PasswordDTO[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.password, flags); + dest.writeStringList(this.methods); + } + + public void readFromParcel(Parcel source) { + this.password = source.readParcelable(PasswordDTO.class.getClassLoader()); + this.methods = source.createStringArrayList(); + } + + public IdentityDTO() { + } + + protected IdentityDTO(Parcel in) { + this.password = in.readParcelable(PasswordDTO.class.getClassLoader()); + this.methods = in.createStringArrayList(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public IdentityDTO createFromParcel(Parcel source) { + return new IdentityDTO(source); + } + + @Override + public IdentityDTO[] newArray(int size) { + return new IdentityDTO[size]; + } + }; + } + + public static class ScopeDTO implements Parcelable { + @SerializedName("project") + private ProjectDTO project = new ProjectDTO(); + + @SerializedName("domain") + private IdentityDTO.PasswordDTO.UserDTO.DomainDTO domain = new IdentityDTO.PasswordDTO.UserDTO.DomainDTO(); + + public ProjectDTO getProject() { + return project; + } + + public void setProject(ProjectDTO project) { + this.project = project; + } + + public IdentityDTO.PasswordDTO.UserDTO.DomainDTO getDomain() { + return domain; + } + + public void setDomain(IdentityDTO.PasswordDTO.UserDTO.DomainDTO domain) { + this.domain = domain; + } + + public static class ProjectDTO implements Parcelable { + @SerializedName("name") + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.name); + } + + public void readFromParcel(Parcel source) { + this.name = source.readString(); + } + + public ProjectDTO() { + } + + protected ProjectDTO(Parcel in) { + this.name = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public ProjectDTO createFromParcel(Parcel source) { + return new ProjectDTO(source); + } + + @Override + public ProjectDTO[] newArray(int size) { + return new ProjectDTO[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.project, flags); + dest.writeParcelable(this.domain, flags); + } + + public void readFromParcel(Parcel source) { + this.project = source.readParcelable(ProjectDTO.class.getClassLoader()); + this.domain = source.readParcelable(IdentityDTO.PasswordDTO.UserDTO.DomainDTO.class.getClassLoader()); + } + + public ScopeDTO() { + } + + protected ScopeDTO(Parcel in) { + this.project = in.readParcelable(ProjectDTO.class.getClassLoader()); + this.domain = in.readParcelable(IdentityDTO.PasswordDTO.UserDTO.DomainDTO.class.getClassLoader()); + } + + public static final Creator CREATOR = new Creator() { + @Override + public ScopeDTO createFromParcel(Parcel source) { + return new ScopeDTO(source); + } + + @Override + public ScopeDTO[] newArray(int size) { + return new ScopeDTO[size]; + } + }; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.identity, flags); + dest.writeParcelable(this.scope, flags); + } + + public void readFromParcel(Parcel source) { + this.identity = source.readParcelable(IdentityDTO.class.getClassLoader()); + this.scope = source.readParcelable(ScopeDTO.class.getClassLoader()); + } + + public AuthDTO() { + } + + protected AuthDTO(Parcel in) { + this.identity = in.readParcelable(IdentityDTO.class.getClassLoader()); + this.scope = in.readParcelable(ScopeDTO.class.getClassLoader()); + } + + public static final Creator CREATOR = new Creator() { + @Override + public AuthDTO createFromParcel(Parcel source) { + return new AuthDTO(source); + } + + @Override + public AuthDTO[] newArray(int size) { + return new AuthDTO[size]; + } + }; + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.auth, flags); + } + + public void readFromParcel(Parcel source) { + this.auth = source.readParcelable(AuthDTO.class.getClassLoader()); + } + + public UserToken() { + } + + protected UserToken(Parcel in) { + this.auth = in.readParcelable(AuthDTO.class.getClassLoader()); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public UserToken createFromParcel(Parcel source) { + return new UserToken(source); + } + + @Override + public UserToken[] newArray(int size) { + return new UserToken[size]; + } + }; +} diff --git a/app/src/main/java/com/huawei/cloudapp/common/CasConnectInfo.java b/app/src/main/java/com/huawei/cloudapp/model/bean/management/CasConnectInfo.java similarity index 98% rename from app/src/main/java/com/huawei/cloudapp/common/CasConnectInfo.java rename to app/src/main/java/com/huawei/cloudapp/model/bean/management/CasConnectInfo.java index 555a99c54d9dd4054c00aa3331891f67a80dd311..bb1ad75687fa4f9f0b63de526421ac9be391e8e1 100644 --- a/app/src/main/java/com/huawei/cloudapp/common/CasConnectInfo.java +++ b/app/src/main/java/com/huawei/cloudapp/model/bean/management/CasConnectInfo.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.huawei.cloudapp.common; +package com.huawei.cloudapp.model.bean.management; import android.os.Parcel; import android.os.Parcelable; @@ -35,6 +35,8 @@ import static com.huawei.cloudapp.utils.CasConstantsUtil.TICKET; import static com.huawei.cloudapp.utils.CasConstantsUtil.TOUCH_TIMEOUT; import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_ID; +import com.huawei.cloudapp.common.CASLog; + public class CasConnectInfo implements Parcelable { public static final String BUNDLE_KEY = "CasConnectorInfo_Key"; diff --git a/app/src/main/java/com/huawei/cloudapp/model/direct/ConnectInfoModel.java b/app/src/main/java/com/huawei/cloudapp/model/direct/ConnectInfoModel.java new file mode 100644 index 0000000000000000000000000000000000000000..4e41d716e0c60ed7a6dc40e214e5174680506ef4 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/direct/ConnectInfoModel.java @@ -0,0 +1,187 @@ +package com.huawei.cloudapp.model.direct; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.X_AUTH_TOKEN; +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.huawei.cloudapp.model.IConnectInfoModel; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.ConnectInfos; +import com.huawei.cloudapp.model.bean.direct.CPHError; +import com.huawei.cloudapp.model.bean.management.CasConnectInfo; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + +public class ConnectInfoModel implements IConnectInfoModel { + private static final String TAG = "ConnectInfoModel"; + private String mRequestBodyJson; + @Override + public void getConnectInfo(User user, String phoneId, String region, OnRequestListener onRequestListener) { + String url = "https://cph." + region + ".myhuaweicloud.com/v1/"+ + user.getUserProjectId().get(region) + "/cloud-phone/phones/batch-connection"; + String userTokenExpireTime = user.getUserTokenExpireTimeByRegion(region); + if (userTokenExpireTime == null || userTokenExpireTime.isEmpty() + || Long.parseLong(userTokenExpireTime) < System.currentTimeMillis()) { + onRequestListener.onFailure(new CustomException.TokenExpireException()); + return; + } + Log.d(TAG, "url: " + url); + HashMap requestHeader = new HashMap(); + requestHeader.put(X_AUTH_TOKEN, user.getUserTokenByRegion(region)); + HashMap body = new HashMap<>(); + body.put("phone_ids", Collections.singletonList(phoneId)); + body.put("client_type", "ANDROID"); + Gson gson = new Gson(); + mRequestBodyJson = gson.toJson(body); + Log.d(TAG, "getConnectInfo: " + mRequestBodyJson); + CasHttpUtils.post(url, requestHeader, mRequestBodyJson, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + try { + onRequestListener.onSuccess(parseResponseToConnectInfo(response), 1); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + @Override + public List parseResponseToConnectInfo(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + String rspJsonStr = response.body().string(); + Gson gson = new Gson(); + if (response.code() == HTTP_OK) { + if (rspJsonStr.isEmpty()){ + Log.e(TAG, "Failed to get start param response."); + throw new CustomException.EmptyResponseFromServerException(); + } + + ConnectInfos rsp; + try { + rsp = gson.fromJson(rspJsonStr, ConnectInfos.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "handleGetConnectInfoResponse: Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.FailedToGetConnectInfoException(); + } + if (rsp == null) { + Log.e(TAG, "handleGetConnectInfoResponse: Failed to get rsp from json. " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetConnectInfoException(); + } + Log.d(TAG, "rsp: " + rspJsonStr); + //当前接口只会请求一个手机的信息,所以只需要判断一次。 + if (!rsp.getErrors().isEmpty()) { + Log.e(TAG, "Failed to get connect info, : " + rsp.getErrors().get(0).getErrorMsg()); + throw new CustomException.FailedToGetConnectInfoException(rsp.getErrors().get(0).getErrorMsg()); + } + ConnectInfos.ConnectInfo ConnectInfo = rsp.getConnectInfos().get(0); + return Collections.singletonList( + GenerateConnectInfo(ConnectInfo.getAccessInfo().getAccessIp(), + String.valueOf(ConnectInfo.getAccessInfo().getAccessPort()), + ConnectInfo.getAccessInfo().getSessionId(), + ConnectInfo.getAccessInfo().getTicket(), + ConnectInfo.getPhoneId(), + ConnectInfo.getAccessInfo().getTimestamp())); + } else { + CPHError rsp; + try { + rsp = gson.fromJson(rspJsonStr, CPHError.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneListException(); + } + + if (response.code() == HTTP_BAD_REQUEST || response.code() == HTTP_INTERNAL_ERROR) { + if (rsp.getErrorCode().equals("CPS.0004")) { + Log.e(TAG, "Phone id is invalid, request body :" + mRequestBodyJson + ", rsp: " + rspJsonStr); + throw new CustomException.ParamInvalidException(); + } else if (rsp.getErrorCode().equals("CPS.0358")) { + Log.e(TAG, "client_type is invalid, request body :" + mRequestBodyJson + ", rsp: " + rspJsonStr); + throw new CustomException.ParamInvalidException(); + } else if (rsp.getErrorCode().equals("CPS.0359")) { + Log.e(TAG, "Phone id size is over max limit, request body :" + mRequestBodyJson + ", rsp: " + rspJsonStr); + throw new CustomException.ParamInvalidException(); + } else { + Log.e(TAG, "handleGetConnectInfoResponse: " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetConnectInfoException(rspJsonStr); + } + } else if (response.code() == HTTP_UNAUTHORIZED) { + if (rsp.getErrorCode().equals("APIGW.0301") || rsp.getErrorCode().equals("APIGW.0307")) { + Log.e(TAG, "Token is invalid, need get new token. "); + throw new CustomException.TokenExpireException(); + } else if (rsp.getErrorCode().equals("APIGW.0303") || rsp.getErrorCode().equals("APIGW.0305")) { + Log.e(TAG, "Check whether the account has the permission to request APIs."); + throw new CustomException.NoPermissionException(); + } else { + Log.e(TAG, "Failed to get connect info, " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetConnectInfoException(rspJsonStr); + } + } else if (response.code() == HTTP_FORBIDDEN) { + if (rsp.getErrorCode().equals("APIGW.0302") || rsp.getErrorCode().equals("APIGW.0304") || rsp.getErrorCode().equals("APIGW.0306")) { + Log.e(TAG, "Check whether the account has the permission to request APIs."); + throw new CustomException.NoPermissionException(); + } else { + Log.e(TAG, "Failed to get connect info, : " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetConnectInfoException(rspJsonStr); + } + } else { + Log.e(TAG, "Failed to get connect info, : " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetConnectInfoException(rspJsonStr); + } + } + } + + public CasConnectInfo GenerateConnectInfo(String ip, + String port, + String sessionId, + String ticket, + String aesKey, + String timestamp) throws Exception { + if (ip.isEmpty() || port.isEmpty()) { + throw new CustomException.ConnectInfoErrorException(); + } + if (sessionId.isEmpty()) { + sessionId = UUID.randomUUID().toString().replaceAll("-", ""); + } + CasConnectInfo connectorInfo = new CasConnectInfo(); + connectorInfo.setConnectIp(ip); + connectorInfo.setConnectPort(port); + connectorInfo.setBackgroundTimeout("60"); + connectorInfo.setAvailablePlayTime("0"); + connectorInfo.setSessionId(sessionId); + connectorInfo.setTicket(ticket); + connectorInfo.setAesKey(aesKey); + connectorInfo.setAuthTs(timestamp); + connectorInfo.setTouchTimeout("0"); + + return connectorInfo; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/direct/PhoneModel.java b/app/src/main/java/com/huawei/cloudapp/model/direct/PhoneModel.java new file mode 100644 index 0000000000000000000000000000000000000000..a322aabe302b33d20929db45a351f69fc4f47f6f --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/direct/PhoneModel.java @@ -0,0 +1,393 @@ +package com.huawei.cloudapp.model.direct; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SERVER_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.STATUS; +import static com.huawei.cloudapp.utils.CasConstantsUtil.X_AUTH_TOKEN; + +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.huawei.cloudapp.model.IPhoneModel; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.direct.PhoneJobRequest; +import com.huawei.cloudapp.model.bean.direct.CPHError; +import com.huawei.cloudapp.model.bean.direct.PhoneDetail; +import com.huawei.cloudapp.model.bean.direct.PhoneList; +import com.huawei.cloudapp.model.bean.Phone; +import com.huawei.cloudapp.model.bean.PhoneInfo; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.PhoneJobResponse; +import com.huawei.cloudapp.utils.CasConstantsUtil; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.Response; + +public class PhoneModel implements IPhoneModel { + private static final String TAG = "PhoneModel"; + private String mRegion; + private int mTotalCount; + private String mUrl; + @Override + public void getPhoneList(User user, HashMap condition, String region, String projectId, int offset, int limit, OnRequestListener onRequestListener) { + String userTokenExpireTime = user.getUserTokenExpireTimeByRegion(region); + if (userTokenExpireTime == null || userTokenExpireTime.isEmpty() + || Long.parseLong(userTokenExpireTime) + 5000 < System.currentTimeMillis()) { + onRequestListener.onFailure(new CustomException.TokenExpireException()); + return; + } + mRegion = region; + HashMap requestHeader = new HashMap(); + requestHeader.put(X_AUTH_TOKEN, user.getUserTokenByRegion(region)); + CasHttpUtils.get(getRequestPhoneListUrl(condition, region, projectId, offset, limit), requestHeader, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + try { + onRequestListener.onSuccess(parseResponseToPhoneList(response), mTotalCount); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + @Override + public void getPhoneDetailInfo(User user, String region, String projectId, String phoneId, OnRequestListener onRequestListener) { + String userTokenExpireTime = user.getUserTokenExpireTimeByRegion(region); + if (userTokenExpireTime == null || userTokenExpireTime.isEmpty() + || Long.parseLong(userTokenExpireTime) + 5000 < System.currentTimeMillis()) { + onRequestListener.onFailure(new CustomException.TokenExpireException()); + return; + } + mRegion = region; + HashMap requestHeader = new HashMap(); + requestHeader.put(X_AUTH_TOKEN, user.getUserTokenByRegion(region)); + CasHttpUtils.get(getRequestPhoneDetailUrl(region, projectId, phoneId), requestHeader, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + try { + onRequestListener.onSuccess(parseResponseToPhoneDetail(response), 1); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + @Override + public void resetPhone(User user, + String region, + String projectId, + List phoneIdList, + String imageId, + List> property, + OnRequestListener onRequestListener) { + doRestartOrResetPhone(false, user, region, projectId, phoneIdList, imageId, property, onRequestListener); + } + + + @Override + public void restartPhone(User user, + String region, + String projectId, + List phoneIdList, + String imageId, + List> property, + OnRequestListener onRequestListener) { + + doRestartOrResetPhone(true, user, region, projectId, phoneIdList, imageId, property, onRequestListener); + } + + + private void doRestartOrResetPhone(boolean isRestart, + User user, + String region, + String projectId, + List phoneIdList, + String imageId, + List> property, + OnRequestListener onRequestListener) { + String userTokenExpireTime = user.getUserTokenExpireTimeByRegion(region); + if (userTokenExpireTime == null || userTokenExpireTime.isEmpty() + || Long.parseLong(userTokenExpireTime) + 5000 < System.currentTimeMillis()) { + onRequestListener.onFailure(new CustomException.TokenExpireException()); + return; + } + mRegion = region; + HashMap requestHeader = new HashMap(); + requestHeader.put(X_AUTH_TOKEN, user.getUserTokenByRegion(region)); + + PhoneJobRequest phoneJob = new PhoneJobRequest(); + if (property == null) { + for (int i = 0; i < phoneIdList.size(); i++) { + phoneJob.getPhones().add(new PhoneJobRequest.PhoneProperty(phoneIdList.get(i), null)); + } + } else { + for (int i = 0; i < phoneIdList.size(); i++) { + phoneJob.getPhones().add(new PhoneJobRequest.PhoneProperty(phoneIdList.get(i), property.get(i).toString())); + } + } + Gson gson = new Gson(); + String bodyStr = gson.toJson(phoneJob); + String url = isRestart ? getRequestPhoneRestartUrl(region, projectId) : getRequestPhoneResetUrl(region, projectId); + CasHttpUtils.post(url, requestHeader, bodyStr, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + try { + List jobs = parseResponseToPhoneRestartOrResetJob(response); + onRequestListener.onSuccess(jobs, jobs.size()); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + + private List parseResponseToPhoneList(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + String rspJsonStr = response.body().string(); + Gson gson = new Gson(); + List phoneInfoList = new ArrayList<>(); + if (response.code() == HTTP_OK) { + PhoneList rsp; + try { + rsp = gson.fromJson(rspJsonStr, PhoneList.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneListException(); + } + if (rsp == null) { + Log.e(TAG, "Failed to get rsp from json. " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetPhoneListException(); + } + mTotalCount = rsp.getCount(); + for (Phone phone : rsp.getPhones()) { + //获取phone model规格 + phoneInfoList.add(new PhoneInfo(phone, "", CasConstantsUtil.REGION_INFO.get(mRegion))); + } + } else { + CPHError rsp; + try { + rsp = gson.fromJson(rspJsonStr, CPHError.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneListException(); + } + handleCommonErrorResponse(response, rsp); + Log.e(TAG, "Failed to get phone list. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneListException(); + } + return phoneInfoList; + } + + private List parseResponseToPhoneDetail(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + String rspJsonStr = response.body().string(); + Gson gson = new Gson(); + PhoneDetail phoneDetail = null; + if (response.code() == HTTP_OK) { + try { + phoneDetail = gson.fromJson(rspJsonStr, PhoneDetail.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneDetailException(); + } + if (phoneDetail == null) { + Log.e(TAG, "Failed to get rsp from json. " + response.code() + ", " + rspJsonStr); + throw new CustomException.FailedToGetPhoneDetailException(); + } + } else { + CPHError rsp; + try { + rsp = gson.fromJson(rspJsonStr, CPHError.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneDetailException(); + } + handleCommonErrorResponse(response, rsp); + Log.e(TAG, "Failed to get phone detail. " + rspJsonStr); + throw new CustomException.FailedToGetPhoneDetailException(); + + } + return Collections.singletonList(phoneDetail); + } + + private List parseResponseToPhoneRestartOrResetJob(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + String rspJsonStr = response.body().string(); + Gson gson = new Gson(); + PhoneJobResponse phoneJob = null; + Log.e(TAG, "rsp: " + rspJsonStr); + if (response.code() == HTTP_OK) { + try { + phoneJob = gson.fromJson(rspJsonStr, PhoneJobResponse.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.DeliverJobFailedException(); + } + if (phoneJob == null) { + Log.e(TAG, "Failed to get rsp from json. " + response.code() + ", " + rspJsonStr); + throw new CustomException.DeliverJobFailedException(); + } + } else { + CPHError rsp; + try { + rsp = gson.fromJson(rspJsonStr, CPHError.class); + } catch (JsonSyntaxException e) { + Log.e(TAG, "Failed to parse rsp json. " + rspJsonStr); + throw new CustomException.DeliverJobFailedException(); + } + handleCommonErrorResponse(response, rsp); + Log.e(TAG, "Failed to delivering job. " + rspJsonStr); + throw new CustomException.DeliverJobFailedException(); + + } + return Collections.singletonList(phoneJob); + } + + private void handleCommonErrorResponse(Response response, CPHError rsp) throws IOException { + if (response.code() == HTTP_BAD_REQUEST) { + if (rsp.getErrorCode().equals("CPS.0025")) { + Log.e(TAG, "Phone name is invalid, rsp: " + response.code() + ", " + rsp.getErrorCode() + ", " + rsp.getErrorMsg()+ ", " + rsp.getRequestId()); + throw new CustomException.ParamInvalidException(); + } else if (rsp.getErrorCode().equals("CPS.0086")) { + Log.e(TAG, "Server id is invalid, rsp: " + response.code() + ", " + rsp.getErrorCode() + ", " + rsp.getErrorMsg()+ ", " + rsp.getRequestId()); + throw new CustomException.ParamInvalidException(); + } + } else if (response.code() == HTTP_UNAUTHORIZED) { + if (rsp.getErrorCode().equals("APIGW.0301") || rsp.getErrorCode().equals("APIGW.0307")) { + Log.e(TAG, "Token is invalid, need get new token. "); + throw new CustomException.TokenExpireException(); + } else if (rsp.getErrorCode().equals("APIGW.0303") || rsp.getErrorCode().equals("APIGW.0305")) { + Log.e(TAG, "Check whether the account has the permission to request APIs."); + throw new CustomException.NoPermissionException(); + } + } else if (response.code() == HTTP_FORBIDDEN) { + switch (rsp.getErrorCode()) { + case "APIGW.0302": + case "APIGW.0304": + case "APIGW.0306": + case "CPS.0001": + Log.e(TAG, "Check whether the account has the permission to request APIs."); + throw new CustomException.NoPermissionException(); + case "CPS.0006": + Log.e(TAG, "Role is op_restricted. "); + throw new CustomException.OpRestrictedException(); + case "CPS.0007": + Log.e(TAG, "Role is op_suspended. "); + throw new CustomException.OpSuspendedException(); + case "CPS.0008": + Log.e(TAG, "Role is op_unverified."); + throw new CustomException.OpUnverifiedException(); + } + } else if (response.code() == HTTP_NOT_FOUND) { + switch (rsp.getErrorCode()) { + case "CPS.0005": + Log.e(TAG, "Phone not found."); + throw new CustomException.PhoneNotFoundException(); + case "CPS.0011": + Log.e(TAG, "job not found. "); + throw new CustomException.JobNotFoundException(); + case "CPS.0015": + Log.e(TAG, "Server not found. "); + throw new CustomException.ServerNotFoundException(); + case "CPS.0243": + Log.e(TAG, "User not found."); + throw new CustomException.UserNotFoundException(); + case "CPS.0302": + Log.e(TAG, "User not found."); + throw new CustomException.ResourceNotFoundException(); + } + } else if (response.code() == HTTP_INTERNAL_ERROR) { + Log.e(TAG, "Service internal error."); + throw new CustomException.ServerError(); + } + } + + private String getRequestPhoneListUrl(HashMap condition, String region, String projectId, int offset, int limit) { + HttpUrl.Builder urlBuilder = HttpUrl.parse("https://cph." + region + ".myhuaweicloud.com/v1/"+ projectId + "/cloud-phone/phones").newBuilder(); + + if (offset >= 0) { + urlBuilder.addQueryParameter("offset", String.valueOf(offset)); + } + + if (limit > 0) { + urlBuilder.addQueryParameter("limit", String.valueOf(limit)); + } + + if (condition != null) { + if (condition.containsKey("server_id")) { + urlBuilder.addQueryParameter("server_id", condition.get(SERVER_ID)); + } + if (condition.containsKey("phone_name")) { + urlBuilder.addQueryParameter("phone_name", condition.get(PHONE_NAME)); + } + if (condition.containsKey("status")) { + urlBuilder.addQueryParameter("status", condition.get(STATUS)); + } + } + mUrl = urlBuilder.build().toString(); + return mUrl; + } + private String getRequestPhoneDetailUrl(String region, String projectId, String phoneId) { + HttpUrl.Builder urlBuilder = HttpUrl.parse("https://cph." + region + ".myhuaweicloud.com/v1/"+ projectId + "/cloud-phone/phones/" + phoneId).newBuilder(); + mUrl = urlBuilder.build().toString(); + return mUrl; + } + private String getRequestPhoneRestartUrl(String region, String projectId) { + HttpUrl.Builder urlBuilder = HttpUrl.parse("https://cph." + region + ".myhuaweicloud.com/v1/"+ projectId + "/cloud-phone/phones/batch-restart").newBuilder(); + mUrl = urlBuilder.build().toString(); + return mUrl; + } + private String getRequestPhoneResetUrl(String region, String projectId) { + HttpUrl.Builder urlBuilder = HttpUrl.parse("https://cph." + region + ".myhuaweicloud.com/v1/"+ projectId + "/cloud-phone/phones/batch-reset").newBuilder(); + mUrl = urlBuilder.build().toString(); + return mUrl; + } + +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/direct/ServerModel.java b/app/src/main/java/com/huawei/cloudapp/model/direct/ServerModel.java new file mode 100644 index 0000000000000000000000000000000000000000..5c2080314122b160c37f1c7a7a131da618212d6f --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/direct/ServerModel.java @@ -0,0 +1,91 @@ +package com.huawei.cloudapp.model.direct; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.X_AUTH_TOKEN; +import static java.net.HttpURLConnection.HTTP_OK; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.ServerList; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + +public class ServerModel { + private static final String TAG = "ServerModel"; + private int mTotalCount; + + public void getServerList(User user, String region, String projectId, int offset, int limit, OnRequestListener onRequestListener) { + if (Long.parseLong(user.getUserTokenExpireTimeByRegion(region)) < System.currentTimeMillis()) { + onRequestListener.onFailure(new CustomException.TokenExpireException()); + return; + } + HashMap requestHeader = new HashMap(); + requestHeader.put(X_AUTH_TOKEN, user.getUserTokenByRegion(region)); + CasHttpUtils.get(getRequestUrl(region, projectId, offset, limit), requestHeader, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + try { + onRequestListener.onSuccess(parseResponseToPhoneList(response), mTotalCount); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + public List parseResponseToPhoneList(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + List serverList = new ArrayList<>(); + if (response.code() == HTTP_OK) { + String rspJsonStr = response.body().string(); + Gson gson = new Gson(); + ServerList rsp = gson.fromJson(rspJsonStr, ServerList.class); + if (rsp == null) { + Log.e(TAG, "handleGetPhoneListResponse: Failed to get rsp from json. " + response.code() + ", " + response.body().string()); + throw new CustomException.FailedToGetPhoneListException(); + } + mTotalCount = rsp.getCount(); + serverList = rsp.getServers(); + if (serverList.size() == 0) { + throw new CustomException.GetServerListEmptyException(); + } + } else { + Log.e(TAG, "handleGetPhoneListResponse: " + response.code() + ", " + response.body().string()); + throw new CustomException.FailedToGetPhoneListException(); + } + return serverList; + } + + public String getRequestUrl(String region, String projectId, int offset, int limit) { + String url = "https://cph." + region + ".myhuaweicloud.com" + "/v1/" + projectId +"/cloud-phone/servers"; + if (offset >= 0) { + url += "?offset=" + offset; + } + + if (limit > 0) { + url += "&limit=" + limit; + } + return url; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/direct/UserModel.java b/app/src/main/java/com/huawei/cloudapp/model/direct/UserModel.java new file mode 100644 index 0000000000000000000000000000000000000000..d15918c9b0f890f8282c105a4b44e3ac933cd7cc --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/direct/UserModel.java @@ -0,0 +1,140 @@ +package com.huawei.cloudapp.model.direct; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.PASSWORD; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.X_SUBJECT_TOKEN; + +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_CREATED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.IUserModel; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.UserToken; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + +public class UserModel implements IUserModel { + + public static final String TAG = "UserModel"; + private static final String IAM_URL = "https://iam.myhuaweicloud.com/v3/auth/tokens?nocatalog=true"; + private User mUser; + private String mRegion; + + @Override + public void getUser(User user, String password, String region, OnRequestListener onRequestListener) { + Map header = new HashMap<>(); + header.put("Content-Type", "application/json;charset=utf8"); + Gson gson = new Gson(); + UserToken userTokenRequest = new UserToken(); + userTokenRequest.getAuth().getIdentity().getMethods().add(PASSWORD); + userTokenRequest.getAuth().getIdentity().getPassword().getUser().getDomain().setName(user.getUsername()); + userTokenRequest.getAuth().getIdentity().getPassword().getUser().setName(user.getIamUsername()); + userTokenRequest.getAuth().getIdentity().getPassword().getUser().setPassword(password); + userTokenRequest.getAuth().getScope().getProject().setName(region); + String userTokenRequestJson = gson.toJson(userTokenRequest); + CasHttpUtils.post(IAM_URL, header, userTokenRequestJson, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + try { + onRequestListener.onSuccess(parseResponseToUser(response), 1); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + mUser = user; + mRegion = region; + } + + @Override + public List parseResponseToUser(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + String tokenStr, tokenExpireTimeStr, projectId = null; + if (response.code() == HTTP_CREATED) { + tokenStr = response.header(X_SUBJECT_TOKEN); + if (tokenStr == null || tokenStr.isEmpty()) { + Log.e(TAG, "Failed to get token."); + throw new CustomException.FailedToGetTokenException(); + } + String rspStr = response.body().string(); + if (rspStr.isEmpty()) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.FailedToGetTokenException(); + } + Gson gson = new Gson(); + JsonObject jsonObject = gson.fromJson(rspStr, JsonObject.class); + String tokenExpireTime = jsonObject.get(TOKEN).getAsJsonObject().get("expires_at").getAsString(); + if (tokenExpireTime == null || tokenExpireTime.isEmpty()) { + Log.e(TAG, "Failed to token expire time."); + throw new CustomException.FailedToGetTokenException(); + } + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + Date date = format.parse(tokenExpireTime); + tokenExpireTimeStr = String.valueOf(date.getTime()); + + projectId = jsonObject.get(TOKEN).getAsJsonObject().get("project").getAsJsonObject().get("id").getAsString(); + Log.e(TAG, "parseResponseToUser: projectId = " + projectId); + } else if (response.code() == HTTP_BAD_REQUEST) { + Log.e(TAG, "The request body is invalid."); + throw new CustomException.BadRequestException(); + } else if (response.code() == HTTP_UNAUTHORIZED) { + Log.e(TAG, "The username or password is wrong."); + throw new CustomException.LogInInfoErrorException(); + } else if (response.code() == HTTP_FORBIDDEN) { + Log.e(TAG, "No permission to get token."); + throw new CustomException.ForbiddenException(); + } else if (response.code() == HTTP_NOT_FOUND) { + Log.e(TAG, "No resource found."); + throw new CustomException.ResourceNotFoundException(); + } else if (response.code() == HTTP_INTERNAL_ERROR) { + Log.e(TAG, "Server internal error."); + throw new CustomException.ServerError(); + } else if (response.code() == HTTP_UNAVAILABLE) { + Log.e(TAG, "Service Unavailable."); + throw new CustomException.ServiceUnavailableException(); + } else { + Log.e(TAG, "Failed to login, code = " + response.code() + ". "); + throw new CustomException.FailedToLogInException(); + } + + mUser.getUserToken().put(mRegion, tokenStr); + mUser.getUserTokenExpireTime().put(mRegion, tokenExpireTimeStr); + mUser.getUserProjectId().put(mRegion, projectId); + return new ArrayList<>(Collections.singletonList(mUser)); + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..d80c021cb8f49070980e02ad0a705be1dfead290 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/management/ConnectInfoModel.java @@ -0,0 +1,175 @@ +package com.huawei.cloudapp.model.management; + +import static com.huawei.cloudapp.utils.CasCommonUtils.getManagementUrl; +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.CONNECTION; +import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_MSG; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IP; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IP_PATTERN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PORT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.POSITIVE_NUMBER_PATTERN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOUCH_TIMEOUT; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.huawei.cloudapp.common.CASLog; +import com.huawei.cloudapp.model.IConnectInfoModel; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.management.CasConnectInfo; +import com.huawei.cloudapp.utils.CasCommonUtils; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import okhttp3.Call; +import okhttp3.Callback; +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"); + Gson gson = new Gson(); + HashMap requestHeader = new HashMap(); + requestHeader.put(TOKEN, user.getUserTokenByRegion(region)); + requestHeader.put(SESSION_ID, user.getUserSessionId()); + CasHttpUtils.post(url, requestHeader, gson.toJson(requestBody), new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + try { + onRequestListener.onSuccess(parseResponseToConnectInfo(response), 1); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + @Override + public List parseResponseToConnectInfo(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + + String rspStr = response.body().string(); + if (rspStr.isEmpty()) { + Log.e(TAG, "Failed to get start param response."); + throw new CustomException.EmptyResponseFromServerException(); + } + Map rspMap = CasCommonUtils.parseJsonMessage(rspStr); + if (rspMap.isEmpty()) { + Log.e(TAG, "Failed to get start param response, rspMap is empty."); + throw new CustomException.EmptyResponseFromServerException(); + } + if (rspMap.containsKey(ERROR_CODE)) { + if (rspMap.get(ERROR_CODE).equals("CPH.MANAGER.USER.00003")) { + Log.e(TAG, "The session is invalid, need to log in again."); + throw new CustomException.LogInInfoInvalidException(); + } else { + Log.e(TAG, "Failed to get start param response. " + rspMap.get(ERROR_CODE) + ": " + rspMap.get(ERROR_MSG)); + throw new CustomException.FailedToGetConnectInfoException(rspMap.get(ERROR_CODE) + ": " + rspMap.get(ERROR_MSG)); + } + } + + if (!rspMap.containsKey(IP) || !rspMap.containsKey(PORT) || !rspMap.containsKey(SESSION_ID)) { + Log.e(TAG, "The start param is invalid."); + throw new CustomException.ResponseParamsException(); + } + + String ip = (String) rspMap.get(IP); + if (ip == null || !IP_PATTERN.matcher(ip).matches()) { + CASLog.e(TAG, "Parameter: ip is invalid."); + throw new CustomException.ResponseParamsException(); + } + + String port = String.valueOf(((Double) rspMap.get(PORT)).intValue()); + if (port.isEmpty() || !POSITIVE_NUMBER_PATTERN.matcher(port).matches()) { + CASLog.e(TAG, "Parameter: port is invalid."); + throw new CustomException.ResponseParamsException(); + } + + String sessionId = (String) rspMap.get(SESSION_ID); + if (sessionId == null) { + CASLog.e(TAG, "Parameter: session_id is invalid."); + throw new CustomException.ResponseParamsException(); + } + + String backgroundTimeout = String.valueOf(((Double) rspMap.get(BACKGROUND_TIMEOUT)).intValue()); + if (backgroundTimeout.isEmpty()) { + CASLog.e(TAG, "Parameter: backgroundTimeout is invalid."); + throw new CustomException.ResponseParamsException(); + } + + String availablePlaytime = String.valueOf(((Double) rspMap.get(AVAILABLE_PLAYTIME)).intValue()); + if (availablePlaytime.isEmpty()) { + CASLog.e(TAG, "Parameter: available_playtime is invalid."); + throw new CustomException.ResponseParamsException(); + } + + String touchTimeout = String.valueOf(((Double) rspMap.get(TOUCH_TIMEOUT)).intValue()); + if (touchTimeout.isEmpty()) { + CASLog.e(TAG, "Parameter: touch_timeout is invalid."); + throw new CustomException.ResponseParamsException(); + } + + CasConnectInfo mConnectInfo = GenerateConnectInfo(ip, port, sessionId, backgroundTimeout, availablePlaytime, touchTimeout); + return Collections.singletonList(mConnectInfo); + } + + public CasConnectInfo GenerateConnectInfo(String ip, + String port, + String sessionId, + String backgroundTimeout, + String availablePlayTime, + String touchTimeout) { + if (ip.isEmpty() || port.isEmpty()) { + return null; + } + if (sessionId.isEmpty()) { + sessionId = UUID.randomUUID().toString().replaceAll("-", ""); + } + CasConnectInfo connectorInfo = new CasConnectInfo(); + connectorInfo.setConnectIp(ip); + connectorInfo.setConnectPort(port); + connectorInfo.setBackgroundTimeout(backgroundTimeout.isEmpty() ? "60" : backgroundTimeout); + connectorInfo.setAvailablePlayTime(availablePlayTime.isEmpty() ? "0" : availablePlayTime); + connectorInfo.setSessionId(sessionId); + connectorInfo.setTicket("ticket_xxxxxx"); + connectorInfo.setAesKey("11111111111111111111111111111111"); + connectorInfo.setAesKey(mPhoneId); + connectorInfo.setAuthTs("987654321"); + connectorInfo.setTouchTimeout(touchTimeout.isEmpty() ? "0" : touchTimeout); + return connectorInfo; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/model/management/PhoneModel.java b/app/src/main/java/com/huawei/cloudapp/model/management/PhoneModel.java new file mode 100644 index 0000000000000000000000000000000000000000..8812f69fe0cbcaec37ebdf0bbb9c8678e7b1c791 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/management/PhoneModel.java @@ -0,0 +1,129 @@ +package com.huawei.cloudapp.model.management; + +import static com.huawei.cloudapp.utils.CasCommonUtils.getManagementUrl; +import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.LIST; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.huawei.cloudapp.model.IPhoneModel; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.PhoneInfo; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.PhoneDetail; +import com.huawei.cloudapp.model.bean.direct.PhoneJobResponse; +import com.huawei.cloudapp.utils.CasCommonUtils; +import com.huawei.cloudapp.utils.CasConstantsUtil; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + +public class PhoneModel implements IPhoneModel { + private static final String TAG = "PhoneModel"; + + @Override + public void getPhoneList(User user, HashMap condition, String region, String projectId, int offset, int limit, OnRequestListener onRequestListener) { + String url = getManagementUrl() + "/" + PHONE + "/" + LIST; + HashMap requestHeader = new HashMap(); + requestHeader.put(TOKEN, user.getUserTokenByRegion(region)); + requestHeader.put(SESSION_ID, user.getUserSessionId()); + CasHttpUtils.post(url, requestHeader, "", new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + try { + List phoneInfos = parseResponseToPhoneList(response); + onRequestListener.onSuccess(phoneInfos, phoneInfos.size()); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + } + + @Override + public void getPhoneDetailInfo(User user, String region, String projectId, String phoneId, OnRequestListener onRequestListener) { + + } + + @Override + public void resetPhone(User user, + String region, + String projectId, + List phoneIdList, + String imageId, + List> property, + OnRequestListener onRequestListener) { + + } + + @Override + public void restartPhone(User user, + String region, + String projectId, + List phoneIdList, + String imageId, + List> property, + OnRequestListener onRequestListener) { + + } + + public List parseResponseToPhoneList(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + + + String rspStr = response.body().string(); + if (rspStr == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + + //处理结果 + List> responseList = CasCommonUtils.parseJsonListMessage(rspStr); + if (responseList.isEmpty()) { + Map errorRsp = CasCommonUtils.parseJsonMessage(rspStr); + if (errorRsp.containsKey(ERROR_CODE)) { + if (errorRsp.get(ERROR_CODE).equals("CPH.MANAGER.USER.00003")) { + throw new CustomException.LogInInfoInvalidException(); + } + } else { + Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str, " + errorRsp.toString()); + throw new CustomException.FailedToGetPhoneListException(); + } + } + + List phoneInfoList = new ArrayList<>(); + for (Map phoneInfo : responseList) { + if (!phoneInfo.containsKey(PHONE_ID) || !phoneInfo.containsKey(PHONE_NAME)) { + Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str "); + throw new CustomException.FailedToGetPhoneListException(); + } + phoneInfoList.add(new PhoneInfo(phoneInfo.get(PHONE_NAME), "8U-16G-1080P", + phoneInfo.get(PHONE_ID), CasConstantsUtil.REGION_INFO.get(phoneInfo.get(REGION_ID)))); + } + return phoneInfoList; + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..72988834e2260dd8fbd3af8cd818467907ae7650 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/model/management/UserModel.java @@ -0,0 +1,104 @@ +package com.huawei.cloudapp.model.management; + +import static com.huawei.cloudapp.utils.CasCommonUtils.getManagementUrl; +import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_MSG; +import static com.huawei.cloudapp.utils.CasConstantsUtil.LOGIN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PASSWORD; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USER; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.IUserModel; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.utils.CasCommonUtils; +import com.huawei.cloudapp.utils.CasHttpUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Response; + + +public class UserModel implements IUserModel { + + public static final String TAG = "UserModel"; + private User mUser; + private String mRegion; + + @Override + public void getUser(User user, String password, String region, final OnRequestListener onRequestListener) { + Map userInfo = new HashMap<>(); + userInfo.put(USERNAME, user.getUsername()); + userInfo.put(PASSWORD, password); + Gson gson = new Gson(); + String userInfoJson = gson.toJson(userInfo); + CasHttpUtils.post(getRequestUrl(), null, userInfoJson, new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + onRequestListener.onFailure(e); + } + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + try { + onRequestListener.onSuccess(parseResponseToUser(response), 1); + } catch (Exception e) { + onRequestListener.onFailure(e); + } + } + }); + mUser = user; + mRegion = region; + } + + @Override + public List parseResponseToUser(Response response) throws Exception { + if (response == null) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + + String rspStr = response.body().string(); + if (rspStr.isEmpty()) { + Log.e(TAG, "Failed to get response from server."); + throw new CustomException.EmptyResponseFromServerException(); + } + + //处理结果 + Map responseMap = CasCommonUtils.parseJsonMessage(rspStr); + if (responseMap.containsKey(ERROR_CODE)) { + Log.e(TAG, "handleGetPhoneListResponse: error msg is " + responseMap.get(ERROR_MSG)); + if (responseMap.get(ERROR_CODE).equals("CPH.MANAGER.USER.00002")) { + throw new CustomException.LogInInfoErrorException(); + } + throw new CustomException.FailedToLogInException(); + } else if (!responseMap.containsKey(TOKEN) || !responseMap.containsKey(SESSION_ID)) { + Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str, " + responseMap); + throw new CustomException.FailedToLogInException(); + } + + mUser.getUserToken().put(mRegion, (String)responseMap.get(TOKEN)); + mUser.setUserSessionId((String) responseMap.get(SESSION_ID)); + + return new ArrayList<>(Collections.singletonList(mUser)); + } + + public String getRequestUrl() { + return getManagementUrl() + "/" + USER + "/" + LOGIN; + } + +} diff --git a/app/src/main/java/com/huawei/cloudapp/presenter/ConnectInfoPresenter.java b/app/src/main/java/com/huawei/cloudapp/presenter/ConnectInfoPresenter.java new file mode 100644 index 0000000000000000000000000000000000000000..ddffe6a0261e77e10a27a0ada9eb003f3473725f --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/presenter/ConnectInfoPresenter.java @@ -0,0 +1,34 @@ +package com.huawei.cloudapp.presenter; + +import com.huawei.cloudapp.model.IConnectInfoModel; +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.management.CasConnectInfo; + +import java.util.HashMap; +import java.util.List; + +public class ConnectInfoPresenter { + private final IConnectInfoModel mConnectInfoModel; + private final IHandleData mIHandleData; + + public ConnectInfoPresenter(IConnectInfoModel connectInfoModel, IHandleData mIHandleData) { + this.mConnectInfoModel = connectInfoModel; + this.mIHandleData = mIHandleData; + } + + public void getConnectInfo(User user, String phoneId, String region) { + mConnectInfoModel.getConnectInfo(user, phoneId, region, new OnRequestListener() { + @Override + public void onSuccess(List connectInfoList, int count) { + mIHandleData.handleData(connectInfoList, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/presenter/PhonePresenter.java b/app/src/main/java/com/huawei/cloudapp/presenter/PhonePresenter.java new file mode 100644 index 0000000000000000000000000000000000000000..290805ba1f61f9d3c32586be5511c0162d1c498a --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/presenter/PhonePresenter.java @@ -0,0 +1,78 @@ +package com.huawei.cloudapp.presenter; + +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.IPhoneModel; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.PhoneInfo; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.PhoneDetail; +import com.huawei.cloudapp.model.bean.direct.PhoneJobResponse; + +import java.util.HashMap; +import java.util.List; + +public class PhonePresenter { + private final IPhoneModel mPhoneModel; + private final IHandleData mIHandleData; + + public PhonePresenter(IHandleData mIHandleData, IPhoneModel phoneModel) { + this.mPhoneModel = phoneModel; + this.mIHandleData = mIHandleData; + } + + public void getPhoneList(User user, HashMap condition, String region, String projectId, int offset, int limit) { + mPhoneModel.getPhoneList(user, condition, region, projectId, offset, limit, new OnRequestListener() { + @Override + public void onSuccess(List phoneInfo, int count) { + mIHandleData.handleData(phoneInfo, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } + + public void restartPhone(User user, String region, String projectId, String imageId, List> property, List phoneIdList) { + mPhoneModel.restartPhone(user, region, projectId, phoneIdList, imageId, property, new OnRequestListener() { + @Override + public void onSuccess(List phoneJob, int count) { + mIHandleData.handleData(phoneJob, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } + + public void resetPhone(User user, String region, String projectId, String imageId, List> property, List phoneIdList) { + mPhoneModel.resetPhone(user, region, projectId, phoneIdList, imageId, property, new OnRequestListener() { + @Override + public void onSuccess(List phoneJob, int count) { + mIHandleData.handleData(phoneJob, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } + + public void getPhoneDetailInfo(User user, String region, String projectId, String phoneId) { + mPhoneModel.getPhoneDetailInfo(user, region, projectId, phoneId, new OnRequestListener() { + @Override + public void onSuccess(List phoneDetail, int count) { + mIHandleData.handleData(phoneDetail, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/presenter/ServerPresenter.java b/app/src/main/java/com/huawei/cloudapp/presenter/ServerPresenter.java new file mode 100644 index 0000000000000000000000000000000000000000..4682a1a6be06c88b8057d194393f25e398a731f3 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/presenter/ServerPresenter.java @@ -0,0 +1,33 @@ +package com.huawei.cloudapp.presenter; + +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.ServerList; +import com.huawei.cloudapp.model.direct.ServerModel; + +import java.util.List; + +public class ServerPresenter { + private final ServerModel mServerModel; + private final IHandleData mIHandleData; + + public ServerPresenter(ServerModel mServerModel, IHandleData mIHandleData) { + this.mServerModel = mServerModel; + this.mIHandleData = mIHandleData; + } + + public void getServerList(User user, String region, String projectId, int offset, int limit) { + mServerModel.getServerList(user, region, projectId, offset, limit, new OnRequestListener() { + @Override + public void onSuccess(List servers, int count) { + mIHandleData.handleData(servers, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/presenter/UserPresenter.java b/app/src/main/java/com/huawei/cloudapp/presenter/UserPresenter.java new file mode 100644 index 0000000000000000000000000000000000000000..4ed651f1344d81eb774f8fd9a805c93f480f0dd3 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/presenter/UserPresenter.java @@ -0,0 +1,32 @@ +package com.huawei.cloudapp.presenter; + +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.IUserModel; +import com.huawei.cloudapp.model.OnRequestListener; +import com.huawei.cloudapp.model.bean.User; + +import java.util.List; + +public class UserPresenter { + private final IUserModel mUserModel; + private final IHandleData mIHandleData; + + public UserPresenter(IHandleData mIHandleData, IUserModel userModel) { + this.mUserModel = userModel; + this.mIHandleData = mIHandleData; + } + + public void getUser(User user, String password, String region) { + mUserModel.getUser(user, password, region, new OnRequestListener() { + @Override + public void onSuccess(List users, int count) { + mIHandleData.handleData(users, count); + } + + @Override + public void onFailure(Exception e) { + mIHandleData.handleError(e); + } + }); + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudDebugActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/CasCloudDebugActivity.java deleted file mode 100644 index 68cb2e3da3bed6af094bc9bf8c7b0a3071214dd0..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudDebugActivity.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2022 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.cloudapp.ui; - -import static com.huawei.cloudapp.utils.CasConstantsUtil.DEBUG_MODE; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.text.InputFilter; -import android.text.Spanned; -import android.text.TextUtils; -import android.util.Log; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.TextView; - -import com.huawei.cloudapp.R; -import com.huawei.cloudapp.common.CASLog; -import com.huawei.cloudapp.common.CasConnectInfo; -import com.huawei.cloudapp.common.CasRecord; -import com.huawei.cloudapp.utils.CasCommonUtils; -import com.zhy.view.flowlayout.FlowLayout; -import com.zhy.view.flowlayout.TagAdapter; -import com.zhy.view.flowlayout.TagFlowLayout; - -import java.util.Arrays; -import java.util.UUID; - -public class CasCloudDebugActivity extends Activity { - - private static final String TAG = "CasCloudMainActivity"; - private AutoCompleteTextView mCloudPhoneIp; - private AutoCompleteTextView mCloudPhonePort; - private TagFlowLayout mFlowLayout; - private CasRecord mCasRecord; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_cas_cloud_debug); - mCasRecord = new CasRecord(getSharedPreferences("input_history", MODE_PRIVATE)); - initView(); - } - - @Override - protected void onResume() { - super.onResume(); - - initAutoCompleteTextView("ip", mCloudPhoneIp); - initAutoCompleteTextView("port", mCloudPhonePort); - setAdapter(mFlowLayout); - } - - @Override - protected void onPause() { - super.onPause(); - } - - private void initView() { - mCloudPhoneIp = findViewById(R.id.cloud_phone_ip); - initAutoCompleteTextView("ip", mCloudPhoneIp); - mCloudPhonePort = findViewById(R.id.cloud_phone_port); - initAutoCompleteTextView("port", mCloudPhonePort); - mFlowLayout = findViewById(R.id.flow); - setAdapter(mFlowLayout); - - } - - public void cloudPhoneConnect(View view) { - if (CasCommonUtils.isFastClick()) { - return; - } - startCloudPhoneActivity(CasCloudPhoneActivity.class); - } - - private void startCloudPhoneActivity(Class cls) { - String phoneIp = mCloudPhoneIp.getText().toString().trim(); - if (TextUtils.isEmpty(phoneIp)) { - CASLog.e(TAG, "输入Ip为空"); - return; - } - String phonePort = mCloudPhonePort.getText().toString().trim(); - if (TextUtils.isEmpty(phonePort)) { - CASLog.e(TAG, "输入Port为空"); - return; - } - Intent intent = new Intent(CasCloudDebugActivity.this, cls); - CasConnectInfo connectorInfo = getCasConnectorInfo(phoneIp, phonePort); - intent.putExtra(CasConnectInfo.BUNDLE_KEY, connectorInfo); - intent.putExtra(DEBUG_MODE, true); - startActivity(intent); - overridePendingTransition(0, 0); - } - - private CasConnectInfo getCasConnectorInfo(String phoneIp, String phonePort) { - String sessionId = UUID.randomUUID().toString().replaceAll("-", ""); - CasConnectInfo connectorInfo = new CasConnectInfo(); - connectorInfo.setConnectIp(phoneIp); - connectorInfo.setConnectPort(phonePort); - connectorInfo.setBackgroundTimeout("60"); - connectorInfo.setAvailablePlayTime("4800"); - connectorInfo.setSessionId(sessionId); - connectorInfo.setTicket("ticket_xxxxxx"); - // 32位16进制数,测试使用 - connectorInfo.setAesKey("11111111111111111111111111111111"); - connectorInfo.setAuthTs("987654321"); - connectorInfo.setTouchTimeout("0"); - return connectorInfo; - } - - private void initAutoCompleteTextView(String key, AutoCompleteTextView autoCompleteTextView) { - String[] keyHistoryList = mCasRecord.getRecord(key, 10); - ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, keyHistoryList); - autoCompleteTextView.setAdapter(adapter); - autoCompleteTextView.setDropDownHeight(450); - autoCompleteTextView.setCompletionHint("仅显示最近的10条记录"); - autoCompleteTextView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - dropDownItem(view); - } - }); - autoCompleteTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() { - @Override - public void onFocusChange(View view, boolean hasFocus) { - if (hasFocus) { - dropDownItem(view); - } - } - }); - InputFilter filter = new InputFilter() { - public CharSequence filter(CharSequence source, int start, int end, - Spanned dest, int dstart, int dend) { - for (int i = start; i < end; i++) { - char c = source.charAt(i); - if (!Character.isDigit(c) && c != '.') { - return ""; - } - } - return null; - } - }; - autoCompleteTextView.setFilters(new InputFilter[]{filter}); - } - - private void dropDownItem(View view) { - AutoCompleteTextView autoCompleteTextView = ((AutoCompleteTextView) view); - if (autoCompleteTextView.getAdapter().getCount() != 0) { - autoCompleteTextView.showDropDown(); - } else { - autoCompleteTextView.dismissDropDown(); - } - } - - private void setAdapter(TagFlowLayout flowLayout) { - String[] data = mCasRecord.getRecord("ip:port", 10); - if (data.length == 0) return; - flowLayout.setAdapter(new TagAdapter(data) { - @Override - public View getView(FlowLayout parent, int position, String s) { - TextView textView = (TextView) View.inflate(CasCloudDebugActivity.this, R.layout.flow_item, null); - textView.setText(s); - return textView; - } - - @Override - public void onSelected(int position, View view) { - String[] ipAndPortStr = data[position].split(":"); - mCloudPhoneIp.setText(ipAndPortStr[0]); - mCloudPhonePort.setText(ipAndPortStr[1]); - Log.e(TAG, "ipAndPortStr : "+ Arrays.toString(ipAndPortStr)); - } - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudLoginActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/CasCloudLoginActivity.java deleted file mode 100644 index 4519ac09c93a94bb6a90aadf19cbb1f5f89d1a71..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudLoginActivity.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2022 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.cloudapp.ui; - -import static com.huawei.cloudapp.utils.CasCommonUtils.getManagementUrl; -import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_MSG; -import static com.huawei.cloudapp.utils.CasConstantsUtil.LIST; -import static com.huawei.cloudapp.utils.CasConstantsUtil.LOGIN; -import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT_DEV_ENV_URL; -import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT_PROD_ENV_URL; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PASSWORD; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; -import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; -import static com.huawei.cloudapp.utils.CasConstantsUtil.USER; -import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; -import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.util.Log; -import android.view.View; - -import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.textfield.TextInputLayout; -import com.google.gson.Gson; -import com.huawei.cloudapp.R; -import com.huawei.cloudapp.common.CasRecord; -import com.huawei.cloudapp.utils.CasCommonUtils; -import com.huawei.cloudapp.utils.CasHttpUtils; - -import java.util.HashMap; -import java.util.Map; - -import shem.com.materiallogin.DefaultLoginView; -import shem.com.materiallogin.MaterialLoginView; - -public class CasCloudLoginActivity extends Activity { - - private static final String TAG = "CasCloudLoginActivity"; - private static final int MSG_GET_LOGIN_RESPONSE = 100; - private static final int MSG_GET_REGISTER_RESPONSE = 101; - private MaterialLoginView loginView; - private CasRecord mRecord; - private String mUsername; - private Handler handler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_GET_LOGIN_RESPONSE: - handleGetResponseMessage((String) msg.obj); - break; - default: - break; - } - } - }; - - private void handleGetResponseMessage(String rspStr) { - if (rspStr == null) { - Log.e(TAG, "Failed to get response from server."); - Snackbar.make(loginView, getResources().getString(R.string.cas_phone_reconnect_server_fail_tip_message), Snackbar.LENGTH_LONG).show(); - return; - } - - //处理结果 - Map responseMap = CasCommonUtils.parseJsonMessage(rspStr); - if (responseMap.containsKey(ERROR_CODE)) { - Log.e(TAG, "handleGetPhoneListResponse: error msg is " + responseMap.get(ERROR_MSG)); - if (responseMap.get(ERROR_CODE).equals("CPH.MANAGER.USER.00002")) { - Snackbar.make(loginView, getResources().getString(R.string.failed_to_login_check_username_and_password), Snackbar.LENGTH_LONG).show(); - } - return; - } else if (!responseMap.containsKey(TOKEN) || !responseMap.containsKey(SESSION_ID)) { - Snackbar.make(loginView, getResources().getString(R.string.failed_to_login), Snackbar.LENGTH_LONG).show(); - Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str, " + responseMap.toString()); - return; - } - - mRecord.setRecord(USERNAME, mUsername, 1); - mRecord.setRecord(TOKEN, (String) responseMap.get(TOKEN), 1); - mRecord.setRecord(SESSION_ID, (String) responseMap.get(SESSION_ID), 1); - Intent intent = new Intent(CasCloudLoginActivity.this, CasCloudMainActivity.class); - startActivity(intent); - finish(); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_cas_cloud_login); - loginView = findViewById(R.id.login); - mRecord = new CasRecord(getSharedPreferences(USER_INFO, MODE_PRIVATE)); - ((DefaultLoginView)loginView.getLoginView()).setListener(new DefaultLoginView.DefaultLoginViewListener() { - - @Override - public void onLogin(TextInputLayout loginUser, TextInputLayout loginPass) { - String user = loginUser.getEditText().getText().toString(); - if (user.isEmpty()) { - loginUser.setError("User name can't be empty"); - return; - } else if (user.length() >32) { - loginUser.setError("Username is invalid, length should be 1-32."); - return; - } - loginUser.setError(""); - - String pass = loginPass.getEditText().getText().toString(); - if (pass.isEmpty()) { - loginPass.setError("Password can't be empty"); - return; - } else if (pass.length() < 6 || pass.length() >32) { - loginPass.setError("Password is invalid, length should be 6-32."); - return; - } - loginPass.setError(""); - - Map userInfo = new HashMap(); - mUsername = user; - userInfo.put(USERNAME, user); - userInfo.put(PASSWORD, pass); - Gson gson = new Gson(); - String userInfoStr = gson.toJson(userInfo); - String url = getManagementUrl() + "/" + USER + "/" + LOGIN; - CasHttpUtils.post(url, userInfoStr, handler, MSG_GET_LOGIN_RESPONSE); - } - }); - } - - public void cloudPhoneDebug(View view) { - if (!CasCommonUtils.onDisplaySettingButton()) { - return; - } - Intent intent = new Intent(CasCloudLoginActivity.this, CasCloudDebugActivity.class); - startActivity(intent); - } - - @Override - protected void onResume() { - super.onResume(); - String[] usernameList = mRecord.getRecord(USERNAME, 1); - if (usernameList != null && usernameList.length != 0) { - Intent intent = new Intent(CasCloudLoginActivity.this, CasCloudMainActivity.class); - startActivity(intent); - finish(); - } - } - - @Override - protected void onPause() { - super.onPause(); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudLoginActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudLoginActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..056d0d92ee6366c28d65502f58532e596b0166a1 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudLoginActivity.java @@ -0,0 +1,242 @@ +/* + * Copyright 2022 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.cloudapp.ui.activity; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.COMMON; +import static com.huawei.cloudapp.utils.CasConstantsUtil.ENCRYPT_IV; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IAM_USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PASSWORD; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PROJECT_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SELECTED_REGION_POSITION; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN_EXPIRE_TIME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import com.hjq.toast.ToastParams; +import com.hjq.toast.Toaster; +import com.hjq.toast.style.CustomToastStyle; +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.common.CasRecord; +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.IUserModel; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.presenter.UserPresenter; +import com.huawei.cloudapp.ui.views.MaterialLoginView; +import com.huawei.cloudapp.utils.CasAESKeystoreUtils; +import com.huawei.cloudapp.utils.CasCommonUtils; + +import java.util.HashMap; +import java.util.List; + + +public class CasCloudLoginActivity extends Activity implements IHandleData { + + private static final String TAG = "CasCloudLoginActivity"; + private MaterialLoginView loginView; + private CasRecord mUserRecord; + private UserPresenter mUserPresenter; + private IUserModel mUserModel; + private String selectedRegion; + private String mPass; + private User mUser; + + @Override + protected void onCreate(Bundle savedInstanceState) { + Toaster.init(getApplication()); + overridePendingTransition(0, 0); + super.onCreate(savedInstanceState); + mUserRecord = new CasRecord(getSharedPreferences(USER_INFO, MODE_PRIVATE)); + if (!CasCommonUtils.isDirectMode()) { + selectedRegion = MANAGEMENT; + } else { + CasRecord mCommonRecord = new CasRecord(getSharedPreferences(COMMON, MODE_PRIVATE)); + String selectedRegionPosition = mCommonRecord.getRecord(SELECTED_REGION_POSITION); + if (selectedRegionPosition == null || selectedRegionPosition.isEmpty() || Integer.parseInt(selectedRegionPosition) < 0) { + selectedRegion = REGION_NAME.get(6); + } else { + selectedRegion = REGION_NAME.get(Integer.parseInt(selectedRegionPosition)); + } + } + initView(); + } + + private void initView() { + setContentView(R.layout.activity_cas_cloud_login); + loginView = findViewById(R.id.login); + loginView.setIamEnable(CasCommonUtils.isDirectMode()); + loginView.setListener((loginUser, loginIamUser, loginPass, isUseIam) -> { + + String userStr = loginUser.getEditText().getText().toString(); + if (userStr.isEmpty()) { + loginUser.setError("User name can't be empty"); + return; + } else if (userStr.length() >32) { + loginUser.setError("Username is invalid, length should be 1-32."); + return; + } + loginUser.setError(""); + + String iamUser = null; + if (CasCommonUtils.isDirectMode()) { + if (isUseIam) { + + iamUser = loginIamUser.getEditText().getText().toString(); + if (iamUser.isEmpty()) { + loginIamUser.setError("Iam User name can't be empty"); + return; + } else if (userStr.length() >32) { + loginIamUser.setError("Iam Username is invalid, length should be 1-32."); + return; + } + loginIamUser.setError(""); + } + } + + String pass = loginPass.getEditText().getText().toString(); + if (pass.isEmpty()) { + loginPass.setError("Password can't be empty"); + return; + } else if (pass.length() < 6 || pass.length() >32) { + loginPass.setError("Password is invalid, length should be 6-32."); + return; + } + loginPass.setError(""); + + User user = new User(userStr, iamUser, null, null, null, ""); + if (CasCommonUtils.isDirectMode()) { + mUserModel = new com.huawei.cloudapp.model.direct.UserModel(); + } else { + mUserModel = new com.huawei.cloudapp.model.management.UserModel(); + } + mUserPresenter = new UserPresenter(this, mUserModel); + mUserPresenter.getUser(user, pass, selectedRegion); + mPass = pass; + }); + } + + @Override + protected void onResume() { + super.onResume(); + + String username = mUserRecord.getRecord(USERNAME); + if (username == null || username.isEmpty()) { + return; + } + + HashMap tokens = mUserRecord.getHashMapRecord(TOKEN); + HashMap tokenExpireTimes = mUserRecord.getHashMapRecord(TOKEN_EXPIRE_TIME); + if(tokens.containsKey(selectedRegion)) { + if (!CasCommonUtils.isDirectMode()) { + startActivity(); + return; + } + String userTokenExpireTime = tokenExpireTimes.get(selectedRegion); + if (userTokenExpireTime == null || userTokenExpireTime.isEmpty() + || Long.parseLong(userTokenExpireTime) + 5000 < System.currentTimeMillis()) { + getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.user_info_invalid_need_login); + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + return; + } + startActivity(); + } + } + + private void startActivity() { + Intent intent; + if (CasCommonUtils.isDirectMode()) { + intent = new Intent(CasCloudLoginActivity.this, CasCloudMainDirectActivity.class); + } else { + intent = new Intent(CasCloudLoginActivity.this, CasCloudMainManagementActivity.class); + } + startActivity(intent); + finish(); + } + @Override + protected void onPause() { + super.onPause(); + } + + @Override + public void handleData(List list, int count) { + User user = list.get(0); + if (user == null) { + return; + } + + mUserRecord.setRecord(USERNAME, user.getUsername()); + mUserRecord.setRecord(IAM_USERNAME, user.getIamUsername()); + HashMap encryptResult = CasAESKeystoreUtils.encryptData(mPass); + + CasCommonUtils.setEncryptPass(encryptResult.get(PASSWORD)); + CasCommonUtils.setEncryptIV(encryptResult.get(ENCRYPT_IV)); + + HashMap tokens = user.getUserToken(); + mUserRecord.setHashMapRecord(TOKEN, tokens); + + HashMap tokenExpireTimes = user.getUserTokenExpireTime(); + mUserRecord.setHashMapRecord(TOKEN_EXPIRE_TIME, tokenExpireTimes); + + HashMap projectIds = user.getUserProjectId(); + mUserRecord.setHashMapRecord(PROJECT_ID, projectIds); + mUserRecord.setRecord(SESSION_ID, list.get(0).getUserSessionId()); + mUser = user; + startActivity(); + } + + @Override + public void handleError(Exception e) { + String toastStr; + if (e instanceof CustomException.LogInInfoErrorException) { + toastStr = getResources().getString(R.string.failed_to_login_check_username_and_password); + } else if (e instanceof CustomException.EmptyResponseFromServerException) { + toastStr = getResources().getString(R.string.cas_phone_connect_server_fail_tip_message); + } else if (e instanceof CustomException.FailedToLogInException) { + toastStr = getResources().getString(R.string.failed_to_login); + } else if (e instanceof CustomException.ForbiddenException) { + toastStr = getResources().getString(R.string.no_permission); + } else if (e instanceof CustomException.ServerError) { + toastStr = getResources().getString(R.string.service_internal_error); + } else if (e instanceof CustomException.ServiceUnavailableException) { + toastStr = getResources().getString(R.string.cas_phone_connect_server_fail_tip_message); + } else { + toastStr = getResources().getString(R.string.failed_to_login); + Log.e(TAG, "handleError: ", e); + } + runOnUiThread(new Runnable() { + @Override + public void run() { + ToastParams params = new ToastParams(); + params.text = toastStr; + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudMainDirectActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudMainDirectActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..641c79916d82a0edb7e76277d18975519dcdba4d --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudMainDirectActivity.java @@ -0,0 +1,230 @@ +package com.huawei.cloudapp.ui.activity; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.util.Log; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; + +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.navigation.NavController; +import androidx.navigation.NavDestination; +import androidx.navigation.NavGraph; +import androidx.navigation.NavGraphNavigator; +import androidx.navigation.NavOptions; +import androidx.navigation.Navigation; +import androidx.navigation.Navigator; +import androidx.navigation.NavigatorProvider; +import androidx.navigation.fragment.FragmentNavigator; +import androidx.navigation.ui.NavigationUI; + +import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.databinding.ActivityCasCloudMainDirectBinding; +import com.huawei.cloudapp.ui.fragment.CloudPhoneFragment; +import com.huawei.cloudapp.ui.fragment.explore.ExploreFragment; +import com.huawei.cloudapp.ui.fragment.home.PhoneListFragment; +import com.huawei.cloudapp.ui.fragment.mine.MineFragment; + +import java.lang.reflect.Field; +import java.util.ArrayDeque; +import java.util.List; +import java.util.Map; + +public class CasCloudMainDirectActivity extends AppCompatActivity { + + private ActivityCasCloudMainDirectBinding binding; + BottomNavigationView menuNavigation; + private Fragment mNavHostFragment; + private CloudPhoneFragment mCloudPhoneFragment; + private Fragment mExploreFragment; + private Fragment mUserFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityCasCloudMainDirectBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + menuNavigation = findViewById(R.id.nav_view); + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main); + NavigationUI.setupWithNavController(binding.navView, navController); + mNavHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment_activity_main); + setFixNavigator(navController); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + + @Override + public void onBackPressed() { + mCloudPhoneFragment = (CloudPhoneFragment) mNavHostFragment.getChildFragmentManager().getPrimaryNavigationFragment(); + if (mCloudPhoneFragment != null + && !mCloudPhoneFragment.isHidden() && mCloudPhoneFragment.onBackPressed()) { + return; + } + finish(); + } + + private void setFixNavigator(NavController navController) { + NavigatorProvider provider = navController.getNavigatorProvider(); + //设置自定义的navigator + FixFragmentNavigator fixFragmentNavigator = + new FixFragmentNavigator(this, mNavHostFragment.getChildFragmentManager(), mNavHostFragment.getId()); + provider.addNavigator(fixFragmentNavigator); + + NavGraph navDestinations = initNavGraph(provider, fixFragmentNavigator); + navController.setGraph(navDestinations); + binding.navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + navController.navigate(item.getItemId()); + return true; + } + }); + } + + private NavGraph initNavGraph(NavigatorProvider provider, FixFragmentNavigator fragmentNavigator) { + NavGraph navGraph = new NavGraph(new NavGraphNavigator(provider)); + + FragmentNavigator.Destination destination1 = fragmentNavigator.createDestination(); + destination1.setId(R.id.navigation_home); + destination1.setClassName(PhoneListFragment.class.getCanonicalName()); + navGraph.addDestination(destination1); + + FragmentNavigator.Destination destination2 = fragmentNavigator.createDestination(); + destination2.setId(R.id.navigation_explore); + destination2.setClassName(ExploreFragment.class.getCanonicalName()); + navGraph.addDestination(destination2); + + FragmentNavigator.Destination destination3 = fragmentNavigator.createDestination(); + destination3.setId(R.id.navigation_mine); + destination3.setClassName(MineFragment.class.getCanonicalName()); + navGraph.addDestination(destination3); + + navGraph.setStartDestination(destination1.getId()); + return navGraph; + } + + @Navigator.Name("fixFragment") + public class FixFragmentNavigator extends FragmentNavigator { + private final String TAG = "ReLoadFragmentNavigator"; + private final Context mContext; + private final FragmentManager mFragmentManager; + private final int mContainerId; + + public FixFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) { + super(context, manager, containerId); + mContext = context; + mFragmentManager = manager; + mContainerId = containerId; + } + + @Nullable + @Override + public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args, @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) { + + if (mFragmentManager.isStateSaved()) { + Log.i(TAG, "Ignoring navigate() call: FragmentManager has already" + + " saved its state"); + return null; + } + String className = destination.getClassName(); + if (className.charAt(0) == '.') { + className = mContext.getPackageName() + className; + } + Fragment frag = mFragmentManager.findFragmentByTag(className); + if (null == frag) { + //不存在,则创建 + frag = instantiateFragment(mContext, mFragmentManager, className, args); + } + + frag.setArguments(args); + final FragmentTransaction ft = mFragmentManager.beginTransaction(); + + int enterAnim = navOptions != null ? navOptions.getEnterAnim() : -1; + int exitAnim = navOptions != null ? navOptions.getExitAnim() : -1; + int popEnterAnim = navOptions != null ? navOptions.getPopEnterAnim() : -1; + int popExitAnim = navOptions != null ? navOptions.getPopExitAnim() : -1; + if (enterAnim != -1 || exitAnim != -1 || popEnterAnim != -1 || popExitAnim != -1) { + enterAnim = enterAnim != -1 ? enterAnim : 0; + exitAnim = exitAnim != -1 ? exitAnim : 0; + popEnterAnim = popEnterAnim != -1 ? popEnterAnim : 0; + popExitAnim = popExitAnim != -1 ? popExitAnim : 0; + ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim); + } + +// ft.replace(mContainerId, frag); + List fragments = mFragmentManager.getFragments(); + for (Fragment fragment : fragments) { + ft.hide(fragment); + } + if (!frag.isAdded()) { + ft.add(mContainerId, frag, className); + } + ft.show(frag); + ft.setPrimaryNavigationFragment(frag); + + final @IdRes int destId = destination.getId(); + + //通过反射获取mBackStack + ArrayDeque mBackStack; + try { + Field field = FragmentNavigator.class.getDeclaredField("mBackStack"); + field.setAccessible(true); + mBackStack = (ArrayDeque) field.get(this); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + final boolean initialNavigation = mBackStack.isEmpty(); + final boolean isSingleTopReplacement = navOptions != null && !initialNavigation + && navOptions.shouldLaunchSingleTop() + && mBackStack.peekLast() == destId; + + boolean isAdded; + if (initialNavigation) { + isAdded = true; + } else if (isSingleTopReplacement) { + if (mBackStack.size() > 1) { + mFragmentManager.popBackStack( + generateBackStackName(mBackStack.size(), mBackStack.peekLast()), + FragmentManager.POP_BACK_STACK_INCLUSIVE); + ft.addToBackStack(generateBackStackName(mBackStack.size(), destId)); + } + isAdded = false; + } else { + ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId)); + isAdded = true; + } + if (navigatorExtras instanceof Extras) { + Extras extras = (Extras) navigatorExtras; + for (Map.Entry sharedElement : extras.getSharedElements().entrySet()) { + ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue()); + } + } + ft.setReorderingAllowed(true); + ft.commit(); + if (isAdded) { + mBackStack.add(destId); + return destination; + } else { + return null; + } + } + + @NonNull + private String generateBackStackName(int backStackIndex, int destId) { + return backStackIndex + "-" + destId; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudMainActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudMainManagementActivity.java similarity index 58% rename from app/src/main/java/com/huawei/cloudapp/ui/CasCloudMainActivity.java rename to app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudMainManagementActivity.java index c3defdadd5cd7f0981104c2416ca2c82ce9f6dfd..05012d08415a2bcf12cb848ec07e8840db24eace 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudMainActivity.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudMainManagementActivity.java @@ -14,21 +14,19 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui; - -import static android.view.View.GONE; -import static com.huawei.cloudapp.utils.CasCommonUtils.getManagementUrl; -import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_MSG; -import static com.huawei.cloudapp.utils.CasConstantsUtil.LIST; -import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT_DEV_ENV_URL; -import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT_PROD_ENV_URL; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE; +package com.huawei.cloudapp.ui.activity; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.COMMON; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IAM_USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT; import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_ID; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PROJECT_ID; import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SELECTED_REGION_POSITION; import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN_EXPIRE_TIME; import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; @@ -36,121 +34,65 @@ import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout; -import android.widget.ImageView; import android.widget.Toast; import androidx.viewpager.widget.ViewPager; +import com.huawei.cloudapp.model.bean.direct.ServerList; +import com.huawei.cloudapp.presenter.PhonePresenter; import com.huawei.cloudapp.R; +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.IPhoneModel; import com.huawei.cloudapp.common.CasCommonDialog; import com.huawei.cloudapp.common.CasRecord; -import com.huawei.cloudapp.common.CasUserInfo; -import com.huawei.cloudapp.ui.surface.CasArcView; -import com.huawei.cloudapp.ui.surface.viewpagecards.PhoneCardItem; -import com.huawei.cloudapp.ui.surface.viewpagecards.CardPagerAdapter; -import com.huawei.cloudapp.ui.surface.viewpagecards.ShadowTransformer; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.ui.views.CasArcView; +import com.huawei.cloudapp.model.bean.PhoneInfo; +import com.huawei.cloudapp.ui.adapter.CardPagerAdapter; +import com.huawei.cloudapp.ui.common.ShadowTransformer; import com.huawei.cloudapp.utils.CasCommonUtils; -import com.huawei.cloudapp.utils.CasConstantsUtil; -import com.huawei.cloudapp.utils.CasHttpUtils; import java.util.HashMap; import java.util.List; -import java.util.Map; -public class CasCloudMainActivity extends Activity { +public class CasCloudMainManagementActivity extends Activity implements IHandleData { private static final String TAG = "CasCloudMainActivity"; - private static final int MSG_GET_LOGOUT_RESPONSE = 100; - private static final int MSG_GET_PHONE_LIST_RESPONSE = 101; + private static final int MSG_GET_START_PARAM_RESPONSE = 102; private static final double PADDING_VIEW_RATIO = 4; + private static final int LIMIT = 30; private ViewPager mViewpager; private CardPagerAdapter mCardPagerAdapter; private ShadowTransformer mShadowTransformer; private CasArcView arcView; private CasRecord mCasRecord; - private CasUserInfo mUserInfo; + private User mUserInfo; + private ServerList.Server mServer = null; + private String mRegion; private boolean isLogin = false; + private int mOffset = 0; private Button appConnect; private CasCommonDialog mDialog; private int mSelectPhoneIndex = 0; - private Handler handler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_GET_LOGOUT_RESPONSE: - break; - case MSG_GET_PHONE_LIST_RESPONSE: - handleGetPhoneListResponse((String) msg.obj); - break; - default: - break; - } - } - }; - - private void handleGetPhoneListResponse(String rspStr) { - if (rspStr == null) { - Log.e(TAG, "Failed to get response from server."); - Toast.makeText(this, getResources().getString(R.string.failed_to_get_phone_list), Toast.LENGTH_SHORT).show(); - return; - } - - //处理结果 - List> responseList = CasCommonUtils.parseJsonListMessage(rspStr); - if (responseList.isEmpty()) { - Map errorRsp = CasCommonUtils.parseJsonMessage(rspStr); - if (errorRsp.containsKey(ERROR_CODE)) { - Log.e(TAG, "handleGetPhoneListResponse: error msg is " + errorRsp.get(ERROR_MSG)); - if (errorRsp.get(ERROR_CODE).equals("CPH.MANAGER.USER.00003")) { - Toast.makeText(this, getResources().getString(R.string.user_info_invalid_need_login), Toast.LENGTH_SHORT).show(); - getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); - Intent intent = new Intent(CasCloudMainActivity.this, CasCloudLoginActivity.class); - startActivity(intent); - finish(); - } else { - Toast.makeText(this, getResources().getString(R.string.failed_to_get_phone_list), Toast.LENGTH_SHORT).show(); - } - } else { - Toast.makeText(this, getResources().getString(R.string.failed_to_get_phone_list), Toast.LENGTH_SHORT).show(); - Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str, " + errorRsp.toString()); - } - return; - } - - for (Map phoneInfo : responseList) { - if (!phoneInfo.containsKey(PHONE_ID) || !phoneInfo.containsKey(PHONE_NAME)) { - Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str "); - return; - } - mCardPagerAdapter.addCardItem(new PhoneCardItem(phoneInfo.get(PHONE_NAME), "8U-16G-1080P", - phoneInfo.get(PHONE_ID), CasConstantsUtil.REGION_INFO.get(phoneInfo.get(REGION_ID)))); - } - - if (mCardPagerAdapter.getCount() == 1) { - startCloudPhoneActivity(CasCloudPhoneActivity.class); - finish(); - } else { - initView(); - } - - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_cas_cloud_main); - mViewpager = findViewById(R.id.viewPager); + setContentView(R.layout.activity_cas_cloud_main_management); appConnect = findViewById(R.id.app_connect); + appConnect.setVisibility(View.GONE); + } + + private void initView() { + mViewpager = findViewById(R.id.viewPager); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); @@ -172,10 +114,7 @@ public class CasCloudMainActivity extends Activity { buttonLayoutParams.height = physicalHeight / 16; buttonLayoutParams.width = physicalWidth / 3; appConnect.setLayoutParams(buttonLayoutParams); - appConnect.setVisibility(GONE); - } - private void initView() { mViewpager.setAdapter(mCardPagerAdapter); mViewpager.setOffscreenPageLimit(3); mViewpager.setCurrentItem(mSelectPhoneIndex); @@ -186,35 +125,65 @@ public class CasCloudMainActivity extends Activity { appConnect.setVisibility(View.VISIBLE); } - private void GetUserPhoneList(CasUserInfo mUserInfo) { + private void GetUserPhoneList(User userInfo) { if (mCardPagerAdapter != null && mCardPagerAdapter.getCount() != 0) { return; } - mCardPagerAdapter = new CardPagerAdapter(this); - HashMap requestHeader = new HashMap(); - requestHeader.put(TOKEN, mUserInfo.getUserToken()); - requestHeader.put(SESSION_ID, mUserInfo.getUserSessionId()); - String url = getManagementUrl() + "/" + PHONE + "/" + LIST; - CasHttpUtils.post(url, requestHeader, "", handler, MSG_GET_PHONE_LIST_RESPONSE); + + if (!CasCommonUtils.isDirectMode()) { + mRegion = MANAGEMENT; + } else { + CasRecord mCommonRecord = new CasRecord(getSharedPreferences(COMMON, MODE_PRIVATE)); + String selectedRegionPosition = mCommonRecord.getRecord(SELECTED_REGION_POSITION); + if (selectedRegionPosition == null || selectedRegionPosition.isEmpty()) { + mRegion = REGION_NAME.get(6); + } else { + mRegion = REGION_NAME.get(Integer.parseInt(selectedRegionPosition)); + } + } + + String projectId = ""; + if (!userInfo.getUserProjectId().isEmpty()) { + projectId = userInfo.getUserProjectId().get(mRegion); + } + + HashMap condition = new HashMap<>(); + IPhoneModel phoneModel; + if (CasCommonUtils.isDirectMode()) { + Intent intent = getIntent(); + Bundle bundle = intent.getExtras(); + if (bundle != null) { + mServer = intent.getParcelableExtra(ServerList.Server.BUNDLE_KEY); + condition.put("server_id", mServer.getServerId()); + } + phoneModel = new com.huawei.cloudapp.model.direct.PhoneModel(); + } else { + phoneModel = new com.huawei.cloudapp.model.management.PhoneModel(); + } + + PhonePresenter phonePresenter = new PhonePresenter(this, phoneModel); + phonePresenter.getPhoneList(userInfo, condition, mRegion, projectId, mOffset, LIMIT); } @Override protected void onResume() { super.onResume(); mCasRecord = new CasRecord(getSharedPreferences(USER_INFO, MODE_PRIVATE)); - String[] usernameList = mCasRecord.getRecord(USERNAME, 1); - if (usernameList == null || usernameList.length == 0) { + String username = mCasRecord.getRecord(USERNAME); + if (username == null || username.isEmpty()) { getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); - Intent intent = new Intent(CasCloudMainActivity.this, CasCloudLoginActivity.class); + Intent intent = new Intent(CasCloudMainManagementActivity.this, CasCloudLoginActivity.class); startActivity(intent); finish(); } else { - mUserInfo = new CasUserInfo(usernameList[0], - mCasRecord.getRecord(TOKEN, 1)[0], - mCasRecord.getRecord(SESSION_ID, 1)[0]); + mUserInfo = new User(username, + mCasRecord.getRecord(IAM_USERNAME), + mCasRecord.getHashMapRecord(TOKEN), + mCasRecord.getHashMapRecord(TOKEN_EXPIRE_TIME), + mCasRecord.getHashMapRecord(PROJECT_ID), + mCasRecord.getRecord(SESSION_ID)); isLogin = true; GetUserPhoneList(mUserInfo); - } } @@ -234,7 +203,7 @@ public class CasCloudMainActivity extends Activity { public void onUserViewClick(View view) { if (!isLogin) { - Intent intent = new Intent(CasCloudMainActivity.this, CasCloudLoginActivity.class); + Intent intent = new Intent(CasCloudMainManagementActivity.this, CasCloudLoginActivity.class); startActivity(intent); finish(); } else { @@ -255,7 +224,7 @@ public class CasCloudMainActivity extends Activity { @Override public void onClick(DialogInterface dialog, int which) { getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); - Intent intent = new Intent(CasCloudMainActivity.this, CasCloudLoginActivity.class); + Intent intent = new Intent(CasCloudMainManagementActivity.this, CasCloudLoginActivity.class); startActivity(intent); finish(); } @@ -270,11 +239,11 @@ public class CasCloudMainActivity extends Activity { } public void cloudPhoneDebug(View view) { - if (!CasCommonUtils.onDisplaySettingButton()) { - return; - } - Intent intent = new Intent(CasCloudMainActivity.this, CasCloudDebugActivity.class); - startActivity(intent); +// if (!CasCommonUtils.onJumpToDebugView()) { +// return; +// } +// Intent intent = new Intent(CasCloudManagementMainActivity.this, CasCloudDebugActivity.class); +// startActivity(intent); } public void cloudPhoneConnect(View view) { @@ -285,7 +254,7 @@ public class CasCloudMainActivity extends Activity { } private void startCloudPhoneActivity(Class cls) { - Intent intent = new Intent(CasCloudMainActivity.this, cls); + Intent intent = new Intent(CasCloudMainManagementActivity.this, cls); if (mViewpager != null && mCardPagerAdapter != null && mCardPagerAdapter.getCount() == 0) { return; @@ -300,9 +269,58 @@ public class CasCloudMainActivity extends Activity { return; } intent.putExtra(PHONE_ID, phoneId); - intent.putExtra(CasUserInfo.BUNDLE_KEY, mUserInfo); + intent.putExtra(User.BUNDLE_KEY, mUserInfo); + intent.putExtra(REGION_ID, mRegion); startActivity(intent); overridePendingTransition(0, 0); } + + @Override + public void handleData(List list, int count) { + + mCardPagerAdapter = new CardPagerAdapter(this); + for (PhoneInfo phoneInfo : list) { + if (phoneInfo.getPhoneId().isEmpty() || phoneInfo.getName().isEmpty()) { + Log.e(TAG, "handleGetPhoneListResponse: failed to parse response json str "); + return; + } + mCardPagerAdapter.addCardItem(phoneInfo); + } + mOffset += LIMIT; + + runOnUiThread(new Runnable() { + @Override + public void run() { + if (mCardPagerAdapter.getCount() == 1) { + startCloudPhoneActivity(CasCloudPhoneActivity.class); + finish(); + } else { + initView(); + } + } + }); + } + + @Override + public void handleError(Exception e) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (e instanceof CustomException.LogInInfoInvalidException) { + Toast.makeText(CasCloudMainManagementActivity.this, getResources().getString(R.string.user_info_invalid_need_login), Toast.LENGTH_SHORT).show(); + getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); + Intent intent = new Intent(CasCloudMainManagementActivity.this, CasCloudLoginActivity.class); + startActivity(intent); + finish(); + } else if (e instanceof CustomException.EmptyResponseFromServerException || + e instanceof CustomException.FailedToGetPhoneListException) { + Toast.makeText(CasCloudMainManagementActivity.this, getResources().getString(R.string.failed_to_get_phone_list), Toast.LENGTH_SHORT).show(); + } else { + Log.e(TAG, "handleError: ", e); + } + } + }); + + } } \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java similarity index 75% rename from app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java rename to app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java index 1db0370a3710856a86e42b3cfaf637f143f483ad..91efb6654702ca8733f43ba558a3e6ae53299d5c 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/CasCloudPhoneActivity.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/CasCloudPhoneActivity.java @@ -14,7 +14,43 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui; +package com.huawei.cloudapp.ui.activity; + +import static android.os.SystemClock.sleep; +import static com.huawei.cloudapp.utils.CasCommonUtils.isSupportH265; +import static com.huawei.cloudapp.utils.CasConstantsUtil.AES_KEY; +import static com.huawei.cloudapp.utils.CasConstantsUtil.AUTH_TS; +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.DEFINITION_BEST; +import static com.huawei.cloudapp.utils.CasConstantsUtil.DIRECT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.FRAME_TYPE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.FRAME_TYPE_H265; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IAM_USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IP; +import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHYSICAL_HEIGHT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHYSICAL_WIDTH; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PORT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PROJECT_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.QUALITY; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.RESOLUTION_1080P; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TICKET; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN_EXPIRE_TIME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOUCH_TIMEOUT; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; +import static com.huawei.cloudapp.utils.CasConstantsUtil.WIDTH; +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.utils.CasConstantsUtil.CLIENT_MODE; import android.annotation.SuppressLint; import android.app.Activity; @@ -30,10 +66,6 @@ import android.os.Build; 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; import android.util.Log; import android.view.Gravity; @@ -47,19 +79,31 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import androidx.core.app.ActivityCompat; +import androidx.fragment.app.FragmentActivity; + import com.google.gson.Gson; +import com.hjq.toast.ToastParams; +import com.hjq.toast.Toaster; +import com.hjq.toast.style.CustomToastStyle; import com.huawei.cloudapp.BuildConfig; import com.huawei.cloudapp.R; import com.huawei.cloudapp.common.CASLog; import com.huawei.cloudapp.common.CasCommonDialog; -import com.huawei.cloudapp.common.CasConnectInfo; -import com.huawei.cloudapp.common.CasRecord; import com.huawei.cloudapp.common.CasListener; +import com.huawei.cloudapp.common.CasRecord; import com.huawei.cloudapp.common.CasState; -import com.huawei.cloudapp.common.CasUserInfo; +import com.huawei.cloudapp.model.IConnectInfoModel; +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.IUserModel; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.management.CasConnectInfo; +import com.huawei.cloudapp.presenter.ConnectInfoPresenter; +import com.huawei.cloudapp.presenter.UserPresenter; +import com.huawei.cloudapp.utils.CasAESKeystoreUtils; import com.huawei.cloudapp.utils.CasAdaptPhoneUtils; import com.huawei.cloudapp.utils.CasCommonUtils; -import com.huawei.cloudapp.utils.CasHttpUtils; import com.huawei.cloudphone.api.CloudAppDataListener; import com.huawei.cloudphone.api.CloudPhoneClipboardListener; import com.huawei.cloudphone.api.CloudPhoneManager; @@ -71,50 +115,9 @@ import com.huawei.cloudphone.api.CloudPhoneStateListener; import com.huawei.cloudphone.api.ICloudPhone; import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import static android.os.SystemClock.sleep; -import static com.huawei.cloudapp.utils.CasCommonUtils.getManagementUrl; -import static com.huawei.cloudapp.utils.CasCommonUtils.isSupportH265; -import static com.huawei.cloudapp.utils.CasConstantsUtil.AES_KEY; -import static com.huawei.cloudapp.utils.CasConstantsUtil.ALLOCATION; -import static com.huawei.cloudapp.utils.CasConstantsUtil.AUTH_TS; -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.CONNECTION; -import static com.huawei.cloudapp.utils.CasConstantsUtil.DEBUG_MODE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.DEFINITION_BEST; -import static com.huawei.cloudapp.utils.CasConstantsUtil.ERROR_CODE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.FRAME_TYPE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.FRAME_TYPE_H265; -import static com.huawei.cloudapp.utils.CasConstantsUtil.IP; -import static com.huawei.cloudapp.utils.CasConstantsUtil.IP_PATTERN; -import static com.huawei.cloudapp.utils.CasConstantsUtil.LIST; -import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT_DEV_ENV_URL; -import static com.huawei.cloudapp.utils.CasConstantsUtil.MANAGEMENT_PROD_ENV_URL; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_ID; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHYSICAL_HEIGHT; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PHYSICAL_WIDTH; -import static com.huawei.cloudapp.utils.CasConstantsUtil.PORT; -import static com.huawei.cloudapp.utils.CasConstantsUtil.POSITIVE_NUMBER_PATTERN; -import static com.huawei.cloudapp.utils.CasConstantsUtil.QUALITY; -import static com.huawei.cloudapp.utils.CasConstantsUtil.RESOLUTION_1080P; -import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; -import static com.huawei.cloudapp.utils.CasConstantsUtil.TICKET; -import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; -import static com.huawei.cloudapp.utils.CasConstantsUtil.TOUCH_TIMEOUT; -import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_ID; -import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; -import static com.huawei.cloudapp.utils.CasConstantsUtil.WIDTH; -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 java.util.List; -public class CasCloudPhoneActivity extends FragmentActivity { +public class CasCloudPhoneActivity extends FragmentActivity implements IHandleData { private static final String TAG = "CasCloudPhoneActivity"; // Intent Trans Key @@ -144,17 +147,18 @@ public class CasCloudPhoneActivity extends FragmentActivity { private CasCommonDialog quitDialog; private CasCommonDialog mDialog; private CasRecord mCasRecord; + private CasRecord mCasUserRecord; // intent trans value private CasConnectInfo mConnectInfo; - private CasUserInfo mUserInfo; + private User mUserInfo; private String mPhoneId; + private String mSelectedRegion; private boolean bIsStart = false; private int mOrientation = 0; private String mFrameType = FRAME_TYPE_H265; private String mResolution = RESOLUTION_1080P; private FrameLayout mFrameLayout = null; - private boolean mIsDebugMode = false; private boolean mIsTrailPlayTimeout = false; private boolean mIsActivityBackground = false; private boolean mIsStopCloudPhoneCalled = false; @@ -185,9 +189,6 @@ public class CasCloudPhoneActivity extends FragmentActivity { case MSG_RECONNECT_FAILED: showDialog(getResources().getString(R.string.cas_phone_reconnect_server_fail_tip_message)); break; - case MSG_GET_START_PARAM_RESPONSE: - handleGetResponseMsg((String) msg.obj); - break; case MSG_CANCLE_EXIT: isReadyToExit = false; mToast.cancel(); @@ -297,34 +298,9 @@ public class CasCloudPhoneActivity extends FragmentActivity { getWindowManager().getDefaultDisplay().getRealMetrics(metrics); mMediaConfig.put(PHYSICAL_WIDTH, String.valueOf(metrics.widthPixels)); mMediaConfig.put(PHYSICAL_HEIGHT, String.valueOf(metrics.heightPixels)); - mCloudPhone.setMediaConfig(mMediaConfig); - if (mIsDebugMode) { - HashMap parasMap = new HashMap(); - parasMap.put(IP, mConnectInfo.getConnectIp()); - parasMap.put(PORT, mConnectInfo.getConnectPort()); - parasMap.put(SESSION_ID, mConnectInfo.getSessionId()); - parasMap.put(TICKET, mConnectInfo.getTicket()); - parasMap.put(AES_KEY, mConnectInfo.getAesKey()); - parasMap.put(AUTH_TS, mConnectInfo.getAuthTs()); - parasMap.put(BACKGROUND_TIMEOUT, mConnectInfo.getBackgroundTimeout()); - parasMap.put(AVAILABLE_PLAYTIME, mConnectInfo.getAvailablePlayTime()); - parasMap.put(USER_ID, mConnectInfo.getUserId()); - parasMap.put(TOUCH_TIMEOUT, mConnectInfo.getTouchTimeout()); - mCloudPhone.startCloudPhone(this, mFrameLayout, parasMap); - } else { - Gson gson = new Gson(); - HashMap requestBody = new HashMap(); - requestBody.put(PHONE_ID, mPhoneId); - requestBody.put(CLIENT_TYPE, "ANDROID"); - HashMap requestHeader = new HashMap(); - requestHeader.put(TOKEN, mUserInfo.getUserToken()); - requestHeader.put(SESSION_ID, mUserInfo.getUserSessionId()); - - String url = getManagementUrl() + "/" + CONNECTION + "/" + ALLOCATION; - CasHttpUtils.post(url, requestHeader, gson.toJson(requestBody), handler, MSG_GET_START_PARAM_RESPONSE); - } + getPhoneConnectInfo(mPhoneId); } catch (IllegalArgumentException e) { showDialog(getResources().getString(R.string.cas_phone_input_param_invalid)); } catch (Exception e) { @@ -436,15 +412,16 @@ public class CasCloudPhoneActivity extends FragmentActivity { Intent intent = getIntent(); Bundle bundle = intent.getExtras(); if (bundle != null) { - mIsDebugMode = bundle.getBoolean(DEBUG_MODE); - if (mIsDebugMode) { - mConnectInfo = intent.getParcelableExtra(CasConnectInfo.BUNDLE_KEY); - } else { - mUserInfo = intent.getParcelableExtra(CasUserInfo.BUNDLE_KEY); - mPhoneId = bundle.getString(PHONE_ID); - } + mUserInfo = intent.getParcelableExtra(User.BUNDLE_KEY); + mPhoneId = bundle.getString(PHONE_ID); + mSelectedRegion = bundle.getString(REGION_ID); mOrientation = bundle.getInt(ORIENTATION); mMediaConfig = (HashMap) bundle.getSerializable(MEDIA_CONFIG); + if (mUserInfo == null || mPhoneId == null || mPhoneId.isEmpty() + || mSelectedRegion == null || mSelectedRegion.isEmpty()) { + showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); + Log.e(TAG, "The data from intent is empty. "); + } } } @@ -455,11 +432,6 @@ public class CasCloudPhoneActivity extends FragmentActivity { mProgressBar.setVisibility(View.GONE); setStartSuccessFlag(); handleStartSuccessMsg(msg); - if (mIsDebugMode) { - mCasRecord.setRecord("ip", mConnectInfo.getConnectIp(), 10); - mCasRecord.setRecord("port", mConnectInfo.getConnectPort(), 10); - mCasRecord.setRecord("ip:port", mConnectInfo.getConnectIp() + ":" +mConnectInfo.getConnectPort(), 10); - } break; case CasState.CAS_SERVER_UNREACHABLE: showDialog(getResources().getString(R.string.cas_phone_connect_server_fail_tip_message)); @@ -511,12 +483,20 @@ public class CasCloudPhoneActivity extends FragmentActivity { case CasState.CAS_NOTOUCH_TIMEOUT: showDialog(getResources().getString(R.string.cas_notouch_timeout_tip_message)); break; + case CasState.CAS_OTHERS_CONNECTED: + try { + mCloudPhone.exitCloudPhone(); + } catch (Exception e) { + CASLog.e(TAG, "exitCloudPhone failed"); + } + showDialog(getResources().getString(R.string.cas_others_connected)); + break; case CasState.CAS_BACK_HOME: - CASLog.i(TAG, "back home"); + if (isReadyToExit) { stopCloudPhone(); } else { - mToast.setText(R.string.cas_exit_confirmation); + mToast.setText(R.string.cas_exit_phone_confirmation); mToast.show(); handler.sendEmptyMessageDelayed(MSG_CANCLE_EXIT, 1000); isReadyToExit = true; @@ -601,99 +581,6 @@ public class CasCloudPhoneActivity extends FragmentActivity { } } - private void handleGetResponseMsg(String rspStr) { - if (rspStr == null) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - Log.e(TAG, "Failed to get start param response."); - return; - } - Map rspMap = CasCommonUtils.parseJsonMessage(rspStr); - if (rspMap.isEmpty()) { - Log.e(TAG, "Failed to get start param response, rspMap is empty."); - return; - } - if (rspMap.containsKey(ERROR_CODE)) { - if (rspMap.get(ERROR_CODE).equals("CPH.MANAGER.USER.00003")) { - getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); - showDialog(getResources().getString(R.string.user_info_invalid_need_login)); - Log.e(TAG, "The session is invalid, need to log in again."); - } else { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - Log.e(TAG, "Failed to parse start param response. "); - } - return; - } - - if (!rspMap.containsKey(IP) || !rspMap.containsKey(PORT) || !rspMap.containsKey(SESSION_ID)) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - Log.e(TAG, "The start param is invalid."); - return; - } - - String ip = (String) rspMap.get(IP); - if (ip == null || !IP_PATTERN.matcher(ip).matches()) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - CASLog.e(TAG, "Parameter: ip is invalid."); - return; - } - - String port = String.valueOf(((Double) rspMap.get(PORT)).intValue()); - if (port.isEmpty() || !POSITIVE_NUMBER_PATTERN.matcher(port).matches()) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - CASLog.e(TAG, "Parameter: port is invalid."); - return; - } - - String sessionId = (String) rspMap.get(SESSION_ID); - if (sessionId == null) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - CASLog.e(TAG, "Parameter: session_id is invalid."); - return; - } - - String backgroundTimeout = String.valueOf(((Double) rspMap.get(BACKGROUND_TIMEOUT)).intValue()); - if (backgroundTimeout.isEmpty()) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - CASLog.e(TAG, "Parameter: backgroundTimeout is invalid."); - return; - } - - String availablePlaytime = String.valueOf(((Double) rspMap.get(AVAILABLE_PLAYTIME)).intValue()); - if (availablePlaytime.isEmpty()) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - CASLog.e(TAG, "Parameter: available_playtime is invalid."); - return; - } - - String touchTimeout = String.valueOf(((Double) rspMap.get(TOUCH_TIMEOUT)).intValue()); - if (touchTimeout.isEmpty()) { - showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); - CASLog.e(TAG, "Parameter: touch_timeout is invalid."); - return; - } - - mConnectInfo = getCasConnectorInfo(ip, port, sessionId, backgroundTimeout, availablePlaytime, touchTimeout); - HashMap parasMap = new HashMap(); - parasMap.put(IP, mConnectInfo.getConnectIp()); - parasMap.put(PORT, mConnectInfo.getConnectPort()); - parasMap.put(SESSION_ID, mConnectInfo.getSessionId()); - parasMap.put(TICKET, mConnectInfo.getTicket()); - parasMap.put(AES_KEY, mConnectInfo.getAesKey()); - parasMap.put(AUTH_TS, mConnectInfo.getAuthTs()); - parasMap.put(BACKGROUND_TIMEOUT, mConnectInfo.getBackgroundTimeout()); - parasMap.put(AVAILABLE_PLAYTIME, mConnectInfo.getAvailablePlayTime()); - parasMap.put(USER_ID, mConnectInfo.getUserId()); - parasMap.put(TOUCH_TIMEOUT, mConnectInfo.getTouchTimeout()); - - try { - mCloudPhone.startCloudPhone(this, mFrameLayout, parasMap); - } catch (IllegalArgumentException e) { - showDialog(getResources().getString(R.string.cas_phone_input_param_invalid)); - } catch (Exception e) { - showDialog(getResources().getString(R.string.cas_phone_start_fail_tip_message)); - } - } - private void handlePermissionMsg(CloudPhonePermissionInfo permissionInfo) { if (permissionInfo != null) { ActivityCompat.requestPermissions(this, permissionInfo.getPermissions(), permissionInfo.getRequestCode()); @@ -894,35 +781,176 @@ public class CasCloudPhoneActivity extends FragmentActivity { } } - private CasConnectInfo getCasConnectorInfo(String ip, - String port, - String sessionId, - String backgroundTimeout, - String availablePlayTime, - String touchTimeout) { - if (ip.isEmpty() || port.isEmpty()) { - return null; - } - if (sessionId.isEmpty()) { - sessionId = UUID.randomUUID().toString().replaceAll("-", ""); - } - CasConnectInfo connectorInfo = new CasConnectInfo(); - connectorInfo.setConnectIp(ip); - connectorInfo.setConnectPort(port); - connectorInfo.setBackgroundTimeout(backgroundTimeout.isEmpty() ? "60" : backgroundTimeout); - connectorInfo.setAvailablePlayTime(availablePlayTime.isEmpty() ? "0" : availablePlayTime); - connectorInfo.setSessionId(sessionId); - connectorInfo.setTicket("ticket_xxxxxx"); - // 32位16进制数,测试使用 - connectorInfo.setAesKey("11111111111111111111111111111111"); - connectorInfo.setAuthTs("987654321"); - connectorInfo.setTouchTimeout(touchTimeout.isEmpty() ? "0" : touchTimeout); - return connectorInfo; - } - private boolean isInView(MotionEvent event, View view) { float x = event.getX(); float y = event.getY(); return x >= 0 && x <= view.getWidth() && y >= 0 && y <= view.getHeight(); } + + private void getPhoneConnectInfo(String phoneId) { + IConnectInfoModel connectInfoModel; + if (CasCommonUtils.isDirectMode()) { + connectInfoModel = new com.huawei.cloudapp.model.direct.ConnectInfoModel(); + } else { + connectInfoModel = new com.huawei.cloudapp.model.management.ConnectInfoModel(); + } + ConnectInfoPresenter presenter = new ConnectInfoPresenter(connectInfoModel, this); + presenter.getConnectInfo(mUserInfo, phoneId, mSelectedRegion); + } + + private void getUserInfo() { + if (mCasUserRecord == null) { + mCasUserRecord = new CasRecord(getSharedPreferences(USER_INFO, MODE_PRIVATE)); + } + String username = mCasUserRecord.getRecord(USERNAME); + if (username == null || username.isEmpty()) { + finishAndReLogin(true); + return; + } + + String pass = CasCommonUtils.getEncryptPass(); + if (pass == null || pass.isEmpty()) { + finishAndReLogin(true); + return; + } + String iv = CasCommonUtils.getEncryptIV(); + if (iv == null || iv.isEmpty()) { + finishAndReLogin(true); + return; + } + String decryptPass = CasAESKeystoreUtils.decryptData(pass, iv); + + if (mUserInfo == null) { + mUserInfo = new User(username, + mCasUserRecord.getRecord(IAM_USERNAME), + mCasUserRecord.getHashMapRecord(TOKEN), + mCasUserRecord.getHashMapRecord(TOKEN_EXPIRE_TIME), + mCasUserRecord.getHashMapRecord(PROJECT_ID), + ""); + } + IUserModel userModel = new com.huawei.cloudapp.model.direct.UserModel(); + UserPresenter userPresenter = new UserPresenter(this, userModel); + userPresenter.getUser(mUserInfo, decryptPass, mSelectedRegion); + } + + private void finishAndReLogin(boolean isPrompt) { + if (isPrompt) { + //提示客户需要重新登陆 + runOnUiThread(new Runnable() { + @Override + public void run() { + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.user_info_invalid_need_login); + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + } + }); + } + getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); + Intent intent = new Intent(this, CasCloudLoginActivity.class); + startActivity(intent); + finish(); + } + + @Override + public void handleData(List list, int count) { + if (count == 0) { + runOnUiThread(new Runnable() { + @Override + public void run() { + showDialog(getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message)); + } + }); + return; + } + + if (((List) list).get(0) instanceof User) { + List users = (List) (List) list; + User user = users.get(0); + mCasUserRecord.setRecord(USERNAME, user.getUsername()); + mCasUserRecord.setRecord(IAM_USERNAME, user.getIamUsername()); + HashMap tokens = user.getUserToken(); + mCasUserRecord.setHashMapRecord(TOKEN, tokens); + HashMap tokenExpireTimes = user.getUserTokenExpireTime(); + mCasUserRecord.setHashMapRecord(TOKEN_EXPIRE_TIME, tokenExpireTimes); + HashMap projectIds = user.getUserProjectId(); + mCasUserRecord.setHashMapRecord(PROJECT_ID, projectIds); + mCasUserRecord.setRecord(SESSION_ID, user.getUserSessionId()); + mUserInfo = user; + getPhoneConnectInfo(mPhoneId); + } else{ + List casConnectInfoList = (List) (List) list; + mConnectInfo = casConnectInfoList.get(0); + HashMap parasMap = new HashMap(); + parasMap.put(IP, mConnectInfo.getConnectIp()); + parasMap.put(PORT, mConnectInfo.getConnectPort()); + parasMap.put(SESSION_ID, mConnectInfo.getSessionId()); + parasMap.put(TICKET, mConnectInfo.getTicket()); + parasMap.put(AES_KEY, mConnectInfo.getAesKey()); + parasMap.put(AUTH_TS, mConnectInfo.getAuthTs()); + parasMap.put(BACKGROUND_TIMEOUT, mConnectInfo.getBackgroundTimeout()); + parasMap.put(AVAILABLE_PLAYTIME, mConnectInfo.getAvailablePlayTime()); + parasMap.put(USER_ID, mConnectInfo.getUserId()); + parasMap.put(TOUCH_TIMEOUT, mConnectInfo.getTouchTimeout()); + parasMap.put(CLIENT_MODE, CasCommonUtils.isDirectMode() ? DIRECT : MANAGEMENT); + parasMap.put(REGION_ID, mSelectedRegion); + runOnUiThread(new Runnable() { + @Override + public void run() { + try { + mCloudPhone.startCloudPhone(CasCloudPhoneActivity.this, mFrameLayout, parasMap); + } catch (IllegalArgumentException e) { + showDialog(getResources().getString(R.string.cas_phone_input_param_invalid)); + } catch (Exception e) { + showDialog(getResources().getString(R.string.cas_phone_start_fail_tip_message)); + } + } + }); + } + + } + + @Override + public void handleError(Exception e) { + Log.e(TAG, "handleError: " + e); + if (e instanceof CustomException.TokenExpireException) { + getUserInfo(); + return; + } + String message; + if (e instanceof CustomException.LogInInfoInvalidException) { + getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); + message = getResources().getString(R.string.user_info_invalid_need_login); + } else if ( + e instanceof CustomException.FailedToGetConnectInfoException) { + message = getResources().getString(R.string.cas_phone_get_auth_param_fail_tip_message); + } else if (e instanceof CustomException.EmptyResponseFromServerException) { + message = getResources().getString(R.string.response_is_empty); + } else if (e instanceof CustomException.ResponseParamsException|| + e instanceof CustomException.ConnectInfoErrorException) { + message = getResources().getString(R.string.connect_info_error); + } else if (e instanceof CustomException.NoPermissionException) { + message = getResources().getString(R.string.no_permission); + }else if (e instanceof CustomException.OpRestrictedException) { + message = getResources().getString(R.string.op_restricted); + } else if (e instanceof CustomException.OpSuspendedException) { + message = getResources().getString(R.string.op_suspended); + } else if (e instanceof CustomException.OpUnverifiedException) { + message = getResources().getString(R.string.op_unverified); + } else if (e instanceof CustomException.ServerError) { + message = getResources().getString(R.string.service_internal_error); + } else if (e instanceof CustomException.ParamInvalidException || + e instanceof CustomException.ResourceNotFoundException) { + message = getResources().getString(R.string.param_invalid); + } else { + message = getResources().getString(R.string.request_failed); + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + showDialog(message); + } + }); + } } \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineAboutActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineAboutActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..d53d4b5d9ac9aa980cb0a5f9e019da735f508ff8 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineAboutActivity.java @@ -0,0 +1,106 @@ +package com.huawei.cloudapp.ui.activity.mine; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.ENTER_STRING; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.common.CasCommonDialog; +import com.huawei.cloudapp.ui.common.ButtonTouchStyleListener; +import com.huawei.cloudapp.utils.CasCommonUtils; + +public class MineAboutActivity extends AppCompatActivity { + + private CasCommonDialog connectUsDialog; + + private static final String CONNECT_MSG1 = "4000-955-988 转 1"; + private static final String CONNECT_MSG2 = "950808 转 1"; + private static final String CONNECT_MSG3 = "为您提供售前购买咨询、解决方案推荐、配置推荐等1v1服务, 助您上云无忧!\n\n热线服务时间 9:00-18:00"; + + @SuppressLint("ClickableViewAccessibility") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_mine_about); + + ImageView backButton = findViewById(R.id.back_button); + backButton.setOnClickListener(view -> onBackPressed()); + + TextView version = findViewById(R.id.about_version); + version.setText(CasCommonUtils.getApkVersion(MineAboutActivity.this)); + + RelativeLayout connectUs = findViewById(R.id.connect_us_linear); + connectUs.setOnTouchListener(new ButtonTouchStyleListener()); + connectUs.setOnClickListener(new MineAboutClickListener()); + + RelativeLayout checkNewVersion = findViewById(R.id.check_new_version_linear); + checkNewVersion.setOnTouchListener(new ButtonTouchStyleListener()); + checkNewVersion.setOnClickListener(new MineAboutClickListener()); + + RelativeLayout privacyPolicy = findViewById(R.id.privacy_policy_linear); + privacyPolicy.setOnTouchListener(new ButtonTouchStyleListener()); + privacyPolicy.setOnClickListener(new MineAboutClickListener()); + } + + class MineAboutClickListener implements View.OnClickListener { + + @Override + public void onClick(View view) { + + switch (view.getId()) { + case R.id.connect_us_linear: + showConnectUsDialog(); + break; + case R.id.check_new_version_linear: + Toast.makeText(view.getContext(), "检查新版本", Toast.LENGTH_SHORT).show(); + break; + case R.id.privacy_policy_linear: + Intent intent = new Intent(MineAboutActivity.this, MineAboutPrivacyPolicyActivity.class); + startActivity(intent); + break; + default: + Toast.makeText(view.getContext(), "空白", Toast.LENGTH_SHORT).show(); + } + } + } + + public void showConnectUsDialog() { + if (connectUsDialog == null || !connectUsDialog.isShowing()) { + final View contentView = View.inflate(MineAboutActivity.this, R.layout.cas_set_ui_level, null); + CasCommonDialog.DialogClickListener dialogListener = new CasCommonDialog.DialogClickListener(); + + final CasCommonDialog.Builder builder = new CasCommonDialog.Builder(MineAboutActivity.this) + .setTitle(R.string.connect_us) + .setMessage(getConnectMsg(MineAboutActivity.this)) + .setContentView(contentView) + .setGravity(Gravity.START) + .setPositiveButton(getResources().getString(R.string.cas_phone_confirm_tip_message), dialogListener); + + connectUsDialog = builder.create(); + connectUsDialog.setCancelable(true); + if (!isFinishing()) { + connectUsDialog.show(); + } + } + } + + private static String getConnectMsg(Context context) { + return CONNECT_MSG1 + + ENTER_STRING + + CONNECT_MSG2 + +ENTER_STRING + + CONNECT_MSG3; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineAboutPrivacyPolicyActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineAboutPrivacyPolicyActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..32e014f7bb62d58f958ce0b6c25f229792904385 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineAboutPrivacyPolicyActivity.java @@ -0,0 +1,21 @@ +package com.huawei.cloudapp.ui.activity.mine; + +import android.os.Bundle; +import android.widget.ImageView; + +import androidx.appcompat.app.AppCompatActivity; + +import com.huawei.cloudapp.R; + +public class MineAboutPrivacyPolicyActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_mine_about_privacy_policy); + + ImageView backButton = findViewById(R.id.back_button); + backButton.setOnClickListener(view -> onBackPressed()); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineGuideActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineGuideActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..f50366800ec20d008ef97607e3aece3bd46bfa09 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineGuideActivity.java @@ -0,0 +1,21 @@ +package com.huawei.cloudapp.ui.activity.mine; + +import android.os.Bundle; +import android.widget.ImageView; + +import androidx.appcompat.app.AppCompatActivity; + +import com.huawei.cloudapp.R; + +public class MineGuideActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_mine_guide); + + ImageView backButton = findViewById(R.id.back_button); + backButton.setOnClickListener(view -> onBackPressed()); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineQuestionActivity.java b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineQuestionActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..8fd3a359fcb9d31e6794608c9bcee0cbc9287585 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/activity/mine/MineQuestionActivity.java @@ -0,0 +1,21 @@ +package com.huawei.cloudapp.ui.activity.mine; + +import android.os.Bundle; +import android.widget.ImageView; + +import androidx.appcompat.app.AppCompatActivity; + +import com.huawei.cloudapp.R; + +public class MineQuestionActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_mine_question); + + ImageView backButton = findViewById(R.id.back_button); + backButton.setOnClickListener(view -> onBackPressed()); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/CardAdapter.java b/app/src/main/java/com/huawei/cloudapp/ui/adapter/CardAdapter.java similarity index 93% rename from app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/CardAdapter.java rename to app/src/main/java/com/huawei/cloudapp/ui/adapter/CardAdapter.java index 0581443d02f68482537830de86acbd7b3a6e6685..624a48ecce129447f760fbb826cc3342d2169cbb 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/CardAdapter.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/adapter/CardAdapter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui.surface.viewpagecards; +package com.huawei.cloudapp.ui.adapter; import androidx.cardview.widget.CardView; diff --git a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/CardPagerAdapter.java b/app/src/main/java/com/huawei/cloudapp/ui/adapter/CardPagerAdapter.java similarity index 84% rename from app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/CardPagerAdapter.java rename to app/src/main/java/com/huawei/cloudapp/ui/adapter/CardPagerAdapter.java index 5247d31112d7e8edea6e2d8ec204fa8451f5600f..2f54a8804e06cd8f9bdef3b9f570e6aaeb89aeef 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/CardPagerAdapter.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/adapter/CardPagerAdapter.java @@ -14,9 +14,8 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui.surface.viewpagecards; +package com.huawei.cloudapp.ui.adapter; -import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.GradientDrawable; import android.view.LayoutInflater; @@ -30,8 +29,8 @@ import androidx.cardview.widget.CardView; import androidx.viewpager.widget.PagerAdapter; import com.huawei.cloudapp.R; +import com.huawei.cloudapp.model.bean.PhoneInfo; import com.huawei.cloudapp.common.CasRecord; -import com.huawei.cloudapp.utils.CasConstantsUtil; import java.util.ArrayList; import java.util.List; @@ -39,7 +38,7 @@ import java.util.List; public class CardPagerAdapter extends PagerAdapter implements CardAdapter { private List mViews; - private List mData; + private List mData; private float mBaseElevation; private Context mContext; private CasRecord mCasRecord; @@ -52,12 +51,34 @@ public class CardPagerAdapter extends PagerAdapter implements CardAdapter { mContext = context; } - public void addCardItem(PhoneCardItem item) { + public void addCardItem(PhoneInfo item) { mViews.add(null); mData.add(item); notifyDataSetChanged(); } + public void addCardItemList(List items) { + for (PhoneInfo phoneInfo : items) { + mViews.add(null); + mData.add(phoneInfo); + } + notifyDataSetChanged(); + } + + public void setCardItemList(List items) { + mData.clear(); + for (PhoneInfo phoneInfo : items) { + mViews.add(null); + mData.add(phoneInfo); + } + notifyDataSetChanged(); + } + + public void removeAllItem(){ + mData.clear(); + notifyDataSetChanged(); + } + public void removeCardItem(int pos) { if (getCount() == 0) { return; @@ -68,11 +89,15 @@ public class CardPagerAdapter extends PagerAdapter implements CardAdapter { removing = false; } - public PhoneCardItem getCardItem(int position) { + public List getAllItem() { + return mData; + } + + public PhoneInfo getCardItem(int position) { if (getCount() == 0) { return null; } - PhoneCardItem item = mData.get(position); + PhoneInfo item = mData.get(position); if (item.getName().isEmpty() && ip != null && port != null) { String ipStr = ip.getText().toString().trim(); String portStr = port.getText().toString().trim(); @@ -150,7 +175,7 @@ public class CardPagerAdapter extends PagerAdapter implements CardAdapter { return index; } - private void bindInfo(PhoneCardItem item, View view) { + private void bindInfo(PhoneInfo item, View view) { TextView titleTextView = view.findViewById(R.id.titleTextView); TextView contentTextView = view.findViewById(R.id.contentTextView); if (item.getName().isEmpty()) { diff --git a/app/src/main/java/com/huawei/cloudapp/ui/adapter/PhoneListAdapter.java b/app/src/main/java/com/huawei/cloudapp/ui/adapter/PhoneListAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..40ee6cf6ec109919c0499a4b94082cee296a4038 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/adapter/PhoneListAdapter.java @@ -0,0 +1,58 @@ +package com.huawei.cloudapp.ui.adapter; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.module.LoadMoreModule; +import com.chad.library.adapter.base.viewholder.BaseViewHolder; +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.model.bean.PhoneInfo; + +public class PhoneListAdapter extends BaseQuickAdapter implements LoadMoreModule { + + public PhoneListAdapter(int layoutResId) { + super(layoutResId); + } + + @Override + protected void convert(@NonNull BaseViewHolder baseViewHolder, PhoneInfo phoneInfo) { + Context context = baseViewHolder.itemView.getContext(); + baseViewHolder.setText(R.id.tv_phone_name, phoneInfo.getPhone().getPhoneName()) + .setText(R.id.tv_phone_id, context.getString(R.string.cloud_phone_info_id) + + phoneInfo.getPhone().getPhoneId()) + .setText(R.id.tv_image_id, context.getString(R.string.cloud_phone_info_image_id) + + phoneInfo.getPhone().getImageId()) + .setText(R.id.tv_phone_model, context.getString(R.string.cloud_phone_info_flavor) + + phoneInfo.getPhone().getPhoneModelName()) + .setBackgroundResource(R.id.iv_phone_status, getBackgroundIdByStatus(phoneInfo.getPhone().getStatus())); + } + + private int getBackgroundIdByStatus(int status) { + int id = R.drawable.cas_status_normal; + switch (status) { + case 1: + case 3: + case 4: + case 7: + id = R.drawable.cas_status_process; + break; + case 2: + id = R.drawable.cas_status_normal; + break; + case 6: + case 8: + id = R.drawable.cas_status_shutdown; + break; + case -5: + case -6: + case -7: + case -8: + case -9: + id = R.drawable.cas_status_error; + break; + } + return id; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/common/ButtonTouchStyleListener.java b/app/src/main/java/com/huawei/cloudapp/ui/common/ButtonTouchStyleListener.java new file mode 100644 index 0000000000000000000000000000000000000000..0bb319225cd56a1464835bcb01b1d9900a3e5cd1 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/common/ButtonTouchStyleListener.java @@ -0,0 +1,31 @@ +package com.huawei.cloudapp.ui.common; + +import android.os.Handler; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +import androidx.core.content.ContextCompat; + +import com.huawei.cloudapp.R; + +public class ButtonTouchStyleListener implements View.OnTouchListener { + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + + if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { + view.setBackgroundColor(ContextCompat.getColor(view.getContext(), R.color.cas_radio_button_unselected_color)); + } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + // 改变TextView的颜色 + view.setBackgroundColor(ContextCompat.getColor(view.getContext(), R.color.cas_white)); + view.performClick(); + } + }, 200); + } + return true; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/ShadowTransformer.java b/app/src/main/java/com/huawei/cloudapp/ui/common/ShadowTransformer.java similarity index 97% rename from app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/ShadowTransformer.java rename to app/src/main/java/com/huawei/cloudapp/ui/common/ShadowTransformer.java index cbb220c140be4df68fd647b8a3cea27f5a4ab2f2..91f55b060aa7484492c6ba12c8ae7fc4b9ada826 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/surface/viewpagecards/ShadowTransformer.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/common/ShadowTransformer.java @@ -14,13 +14,15 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui.surface.viewpagecards; +package com.huawei.cloudapp.ui.common; import android.view.View; import androidx.cardview.widget.CardView; import androidx.viewpager.widget.ViewPager; +import com.huawei.cloudapp.ui.adapter.CardAdapter; + public class ShadowTransformer implements ViewPager.OnPageChangeListener, ViewPager.PageTransformer { private ViewPager mViewPager; diff --git a/app/src/main/java/com/huawei/cloudapp/ui/common/SmoothScroller.java b/app/src/main/java/com/huawei/cloudapp/ui/common/SmoothScroller.java new file mode 100644 index 0000000000000000000000000000000000000000..8552104c53be8226d76a2b79845b72c7c0643b60 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/common/SmoothScroller.java @@ -0,0 +1,19 @@ +package com.huawei.cloudapp.ui.common; + +import android.content.Context; +import android.util.DisplayMetrics; + +import androidx.recyclerview.widget.LinearSmoothScroller; + +public class SmoothScroller extends LinearSmoothScroller { + private static final float SPEED = 9000000f; // 滑动速度,单位是像素每毫秒 + + public SmoothScroller(Context context) { + super(context); + } + + @Override + protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { + return SPEED / displayMetrics.densityDpi; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/fragment/CloudPhoneFragment.java b/app/src/main/java/com/huawei/cloudapp/ui/fragment/CloudPhoneFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..9dc256f667fa9c15be25498808a1130baa1a684e --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/fragment/CloudPhoneFragment.java @@ -0,0 +1,9 @@ +package com.huawei.cloudapp.ui.fragment; + +import androidx.fragment.app.Fragment; + +public class CloudPhoneFragment extends Fragment { + public boolean onBackPressed() { + return false; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/fragment/explore/ExploreFragment.java b/app/src/main/java/com/huawei/cloudapp/ui/fragment/explore/ExploreFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..0ff9878f1f9195c6bccbc8facd16e81a35f52cff --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/fragment/explore/ExploreFragment.java @@ -0,0 +1,115 @@ +package com.huawei.cloudapp.ui.fragment.explore; + +import android.content.pm.ActivityInfo; +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebSettings; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.hjq.toast.Toaster; +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.databinding.FragmentExploreBinding; +import com.huawei.cloudapp.ui.fragment.CloudPhoneFragment; +import com.just.agentweb.AgentWeb; +import com.just.agentweb.DefaultWebClient; +import com.just.agentweb.WebChromeClient; + +public class ExploreFragment extends CloudPhoneFragment { + + private FragmentExploreBinding binding; + private static final String TAG = "ExploreFragment"; + private boolean isReadyToExit = false; + private AgentWeb mAgentWeb; + private LinearLayout mLinearLayout; + private com.just.agentweb.WebViewClient mWebViewClient = new com.just.agentweb.WebViewClient(); + private WebChromeClient mWebChromeClient = new WebChromeClient() { + @Override + public void onShowCustomView(View view, CustomViewCallback customViewCallback) { + super.onShowCustomView(view, customViewCallback); + getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + }; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + + binding = FragmentExploreBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + return root; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mLinearLayout = view.findViewById(R.id.web_view); + + mAgentWeb = AgentWeb.with(this) + .setAgentWebParent(mLinearLayout, -1, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)) + .useDefaultIndicator(-1, 3) + .setSecurityType(AgentWeb.SecurityType.STRICT_CHECK) + .setWebViewClient(mWebViewClient) + .setWebChromeClient(mWebChromeClient) + .setMainFrameErrorView(R.layout.agentweb_error_page, -1) + .setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.DISALLOW) + .interceptUnkownUrl() + .createAgentWeb() + .ready() + .go("https://www.huaweicloud.com/product/cloudphone.html"); + mAgentWeb.getWebCreator().getWebView().setLayerType(View.LAYER_TYPE_HARDWARE, null); + WebSettings webSettings = mAgentWeb.getWebCreator().getWebView().getSettings(); + webSettings.setJavaScriptEnabled(true); + webSettings.setDomStorageEnabled(true); + webSettings.setMediaPlaybackRequiresUserGesture(false); + } + + @Override + public void onResume() { + if (mAgentWeb != null) { + mAgentWeb.getWebLifeCycle().onResume(); + } + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + if (mAgentWeb != null) { + mAgentWeb.getWebLifeCycle().onPause(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (mAgentWeb != null) { + mAgentWeb.getWebLifeCycle().onDestroy(); + } + binding = null; + } + + @Override + public boolean onBackPressed() { + if (mAgentWeb.back()) { + return true; + } + if (!isReadyToExit) { + Toaster.show(R.string.cas_exit_app_confirmation); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + isReadyToExit = false; + } + }, 2000); + isReadyToExit = true; + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huawei/cloudapp/ui/fragment/home/PhoneListFragment.java b/app/src/main/java/com/huawei/cloudapp/ui/fragment/home/PhoneListFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..5bf83577a504dca47379029228c41868ee341912 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/fragment/home/PhoneListFragment.java @@ -0,0 +1,888 @@ +package com.huawei.cloudapp.ui.fragment.home; + +import static android.content.Context.MODE_PRIVATE; +import static android.view.View.GONE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.COMMON; +import static com.huawei.cloudapp.utils.CasConstantsUtil.EMPTY_STRING; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IAM_USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PHONE_STATUS; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PROJECT_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_INFO; +import static com.huawei.cloudapp.utils.CasConstantsUtil.REGION_NAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SELECTED_REGION_POSITION; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SERVER_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.SESSION_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN_EXPIRE_TIME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import android.widget.SearchView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.appcompat.widget.AppCompatSpinner; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.PagerSnapHelper; +import androidx.recyclerview.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.listener.OnItemChildClickListener; +import com.google.android.material.appbar.AppBarLayout; +import com.hjq.toast.ToastParams; +import com.hjq.toast.Toaster; +import com.hjq.toast.style.CustomToastStyle; +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.common.CasCommonDialog; +import com.huawei.cloudapp.common.CasRecord; +import com.huawei.cloudapp.model.IHandleData; +import com.huawei.cloudapp.model.IUserModel; +import com.huawei.cloudapp.model.bean.CustomException; +import com.huawei.cloudapp.model.bean.Phone; +import com.huawei.cloudapp.model.bean.PhoneInfo; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.model.bean.direct.PhoneDetail; +import com.huawei.cloudapp.model.bean.direct.PhoneJobResponse; +import com.huawei.cloudapp.model.direct.PhoneModel; +import com.huawei.cloudapp.presenter.PhonePresenter; +import com.huawei.cloudapp.presenter.UserPresenter; +import com.huawei.cloudapp.ui.activity.CasCloudLoginActivity; +import com.huawei.cloudapp.ui.activity.CasCloudPhoneActivity; +import com.huawei.cloudapp.ui.adapter.PhoneListAdapter; +import com.huawei.cloudapp.ui.fragment.CloudPhoneFragment; +import com.huawei.cloudapp.ui.views.CasArcView; +import com.huawei.cloudapp.utils.CasAESKeystoreUtils; +import com.huawei.cloudapp.utils.CasCommonUtils; +import com.kongzue.dialogx.dialogs.CustomDialog; +import com.kongzue.dialogx.interfaces.OnBindView; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener; +import com.scwang.smart.refresh.layout.listener.OnRefreshListener; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +public class PhoneListFragment extends CloudPhoneFragment implements IHandleData, OnRefreshListener, OnLoadMoreListener { + + private static final String TAG = "PhoneListFragment"; + private static final int LIMIT = 30; + + private Activity mActivity; + private AppCompatSpinner regionSpinner; + private AppCompatSpinner searchSpinner; + private ArrayAdapter regionSpinnerAdapter; + private ArrayAdapter searchTypeSpinnerAdapter; + private SearchView mSearchView; + private CasRecord mCommonCasRecord; + private CasRecord mUserCasRecord; + private boolean isLogin; + private String selectedRegion; + private int selectedQueryType; + private String queryContent = EMPTY_STRING; + private User mUser; + private CasCommonDialog mDialog; + private int offset = 0; + private RecyclerView mRecyclerView; + private SmartRefreshLayout mRefreshLayout; + private int mViewType = 1; + private ImageView mViewTypeIV; + + private PhoneListAdapter mPhoneListAdapter; + private LinearLayoutManager mLayoutManager; + private LinearLayout mLayout; + private LinearLayout mSearchViewLayout; + private LinearLayout mSearchPopupLayout; + private PopupWindow mStatusPopupWindow; + private PopupWindow mSearchPopupWindow; + private AppBarLayout mAppBar; + private TextView mTVPopStatus; + private TextView mTVSearchContent; + private TextView mTVSearchContentClose; + private ImageView mSwitchLayoutIV; + private ImageView mToolbarSearchView; + private CasArcView mArcView; + private Button mEnterCloudPhoneButton; + + private List jobList = new ArrayList<>(); + private boolean isReadyToExit = false; + private boolean isReload = true; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + mUserCasRecord = new CasRecord(getActivity().getSharedPreferences(USER_INFO, MODE_PRIVATE)); + String username = mUserCasRecord.getRecord(USERNAME); + if (username == null || username.isEmpty()) { + finishAndReLogin(true); + } else { + mUser = new User(username, + mUserCasRecord.getRecord(IAM_USERNAME), + mUserCasRecord.getHashMapRecord(TOKEN), + mUserCasRecord.getHashMapRecord(TOKEN_EXPIRE_TIME), + mUserCasRecord.getHashMapRecord(PROJECT_ID), + EMPTY_STRING); + isLogin = true; + } + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + mActivity = (Activity) context; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_home, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mLayout = view.findViewById(R.id.recycler_view_parent); + mCommonCasRecord = new CasRecord(view.getContext().getSharedPreferences(COMMON, MODE_PRIVATE)); + mSwitchLayoutIV = view.findViewById(R.id.cas_view_type); + mSwitchLayoutIV.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + switchLayout(); + } + }); + + mActivity.getWindow().setBackgroundDrawable(AppCompatResources.getDrawable(getContext(), R.drawable.main_background)); + mTVSearchContent = view.findViewById(R.id.tv_search_content); + + mTVSearchContentClose = view.findViewById(R.id.tv_search_content_close); + mTVSearchContentClose.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mTVSearchContent.setText("搜索"); + queryContent = EMPTY_STRING; + mSearchView.setQuery(EMPTY_STRING, false); + mTVSearchContentClose.setVisibility(GONE); + getUserPhoneList(true); + } + }); + + regionSpinner = view.findViewById(R.id.region_spinner); + regionSpinnerAdapter = new ArrayAdapter<>(mActivity, R.layout.spinner_item, new ArrayList<>(REGION_INFO.values())); + regionSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + regionSpinner.setAdapter(regionSpinnerAdapter); + regionSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + if (!isReload && selectedRegion != null && !selectedRegion.isEmpty() && selectedRegion.equals(REGION_NAME.get(i))){ + return; + } + isReload = false; + if (mCommonCasRecord != null) { + mCommonCasRecord.setRecord(SELECTED_REGION_POSITION, String.valueOf(i)); + selectedRegion = REGION_NAME.get(i); + } + HashMap tokens = mUserCasRecord.getHashMapRecord(TOKEN); + if(!tokens.containsKey(selectedRegion)) { + getUserInfo(); + } else { + getUserPhoneList(true); + } + } + @Override + public void onNothingSelected(AdapterView adapterView) { + } + }); + + String selectedRegionPosition = mCommonCasRecord.getRecord(SELECTED_REGION_POSITION); + if (selectedRegionPosition == null || selectedRegionPosition.isEmpty()) { + regionSpinner.setSelection(6); + } else { + regionSpinner.setSelection(Integer.parseInt(selectedRegionPosition)); + } + + mViewTypeIV = view.findViewById(R.id.cas_view_type); + mViewTypeIV.setImageResource(R.drawable.cas_view_carousel); + + mStatusPopupWindow = new PopupWindow(view.getContext()); + mStatusPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); + mStatusPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); + mStatusPopupWindow.setOutsideTouchable(true); + mStatusPopupWindow.setElevation(100f); + mStatusPopupWindow.setFocusable(true); + mStatusPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + mTVPopStatus = (TextView) View.inflate(view.getContext(), R.layout.cas_pop_up_window_status, null); + + mSearchPopupWindow = new PopupWindow(view.getContext()); + mSearchPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); + mSearchPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); + mSearchPopupWindow.setOutsideTouchable(true); + mSearchPopupWindow.setElevation(100f); + mSearchPopupWindow.setFocusable(true); + mSearchPopupLayout = (LinearLayout) View.inflate(view.getContext(), R.layout.cas_search_view, null); + mSearchPopupWindow.setContentView(mSearchPopupLayout); + + mToolbarSearchView = view.findViewById(R.id.toolbar_search_view); + mAppBar = view.findViewById(R.id.main_appbar); + mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (Math.abs(verticalOffset) == mAppBar.getTotalScrollRange()) { + mToolbarSearchView.setVisibility(View.VISIBLE); + } else if (verticalOffset == 0) { + mToolbarSearchView.setVisibility(GONE); + } + } + }); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mAppBar.setOutlineProvider(null); + mToolbarSearchView.setOutlineProvider(ViewOutlineProvider.BOUNDS); + } + + mRefreshLayout = view.findViewById(R.id.refresh_layout); + mRefreshLayout.setEnableLoadMore(true).setOnRefreshListener(this).setOnLoadMoreListener(this).setEnableAutoLoadMore(true); + mArcView = view.findViewById(R.id.arcView); + mEnterCloudPhoneButton = view.findViewById(R.id.app_connect); + + mSearchViewLayout = view.findViewById(R.id.search_layout); + View.OnClickListener listener = new View.OnClickListener() { + @Override + public void onClick(View view) { + showSearchView(mSearchPopupLayout); + } + }; + mSearchViewLayout.setOnClickListener(listener); + mToolbarSearchView.setOnClickListener(listener); + + if (!isReload && mPhoneListAdapter != null) { + offset = 0; + showPhoneList(mPhoneListAdapter.getData(), true, true); + } + } + + // UI + private void prepareRecyclerView() { + mLayout.removeView(mRecyclerView); + mRecyclerView = new RecyclerView(getContext()); + mRecyclerView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + mRecyclerView.setClipToPadding(false); + PagerSnapHelper pagerSnapHelper = new PagerSnapHelper(); + pagerSnapHelper.attachToRecyclerView(mRecyclerView); + + if (mViewType == 0) { + mLayoutManager = new LinearLayoutManager(getContext()); + mPhoneListAdapter = new PhoneListAdapter(R.layout.cas_phone_item_list); + mRecyclerView.clearOnScrollListeners(); + mRecyclerView.setPadding(0, 0, 0, 0); + mArcView.setVisibility(GONE); + mEnterCloudPhoneButton.setVisibility(GONE); + } else { + mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false); + mPhoneListAdapter = new PhoneListAdapter(R.layout.cas_phone_item_card); + mRecyclerView.setPadding(CasCommonUtils.dip2px(getContext(), 30), 0, CasCommonUtils.dip2px(getContext(), 30), 0); + mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + int childCount = recyclerView.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = recyclerView.getChildAt(i); + int left = child.getLeft(); + int paddingStart = recyclerView.getPaddingStart(); + // 遍历recyclerView子项,以中间项左侧偏移量为基准进行缩放 + float bl = Math.min(1, Math.abs(left - paddingStart) * 1f / child.getWidth()); + float scale = (float) (1 - bl * (1 - 0.9)); + child.setScaleY(scale); + } + } + }); + } + mPhoneListAdapter.addChildClickViewIds(R.id.tv_item_reset, R.id.tv_item_restart, + R.id.iv_phone_status, R.id.tv_server_detail, R.id.layout_item, + R.id.tv_phone_name, R.id.tv_phone_id, R.id.tv_phone_model, R.id.tv_image_id, R.id.server_item_layout); + mPhoneListAdapter.setOnItemChildClickListener(new OnItemChildClickListener() { + @Override + public void onItemChildClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) { + Log.e(TAG, "onItemChildClick: "); + Phone phone = mPhoneListAdapter.getItem(position).getPhone(); + if (view.getId() == R.id.tv_item_reset) { + showPhoneActionDialog(false, phone.getPhoneName(), + getResources().getString(R.string.reset_the_phone), + phone.getPhoneId()); + } else if (view.getId() == R.id.tv_item_restart) { + showPhoneActionDialog(true, phone.getPhoneName(), + getResources().getString(R.string.restart_the_phone), + phone.getPhoneId()); + } else if (view.getId() == R.id.iv_phone_status) { + mTVPopStatus.setText(PHONE_STATUS.get(phone.getStatus())); + mStatusPopupWindow.setContentView(mTVPopStatus); + mStatusPopupWindow.showAsDropDown(view); + } else if (view.getId() == R.id.tv_server_detail) { + getPhoneDetail(phone.getPhoneId()); + } else if (view.getId() == R.id.tv_phone_name || view.getId() == R.id.tv_phone_id || view.getId() == R.id.tv_phone_model || view.getId() == R.id.tv_image_id) { + } else { + startCloudPhoneActivity(mPhoneListAdapter.getItem(position)); + } + } + }); + mRecyclerView.setAdapter(mPhoneListAdapter); + mRecyclerView.setLayoutManager(mLayoutManager); + mLayout.addView(mRecyclerView); + + if (mViewType == 0) { + mArcView.setVisibility(GONE); + mEnterCloudPhoneButton.setVisibility(GONE); + } else { + DisplayMetrics metrics = new DisplayMetrics(); + mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + int physicalWidth = metrics.widthPixels; + int physicalHeight = metrics.heightPixels; + ViewGroup.LayoutParams layoutParams = mArcView.getLayoutParams(); + layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; + layoutParams.height = physicalHeight / 6; + mArcView.setLayoutParams(layoutParams); + mArcView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + } + }); + mArcView.bringToFront(); + + CoordinatorLayout.LayoutParams buttonLayoutParams = (CoordinatorLayout.LayoutParams) mEnterCloudPhoneButton.getLayoutParams(); + buttonLayoutParams.setMargins(0, 0, 0, physicalHeight / 15); + buttonLayoutParams.height = physicalHeight / 16; + buttonLayoutParams.width = physicalWidth / 3; + mEnterCloudPhoneButton.setLayoutParams(buttonLayoutParams); + mEnterCloudPhoneButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mPhoneListAdapter.getData().isEmpty()) { + return; + } + int recyclerViewCenterY = mRecyclerView.getHeight() / 2; + int minDistance = Integer.MAX_VALUE; + int centerChildIndex = 0; + for (int i = 0; i < mLayoutManager.getChildCount(); i++) { + View childView = mLayoutManager.getChildAt(i); + int childCenterY = childView.getTop() + childView.getHeight() / 2; + int distance = Math.abs(childCenterY - recyclerViewCenterY); + if (distance < minDistance) { + minDistance = distance; + centerChildIndex = i; + } + } + int position = mLayoutManager.getPosition(mLayoutManager.getChildAt(centerChildIndex)); + startCloudPhoneActivity(mPhoneListAdapter.getItem(position)); + } + }); + mEnterCloudPhoneButton.bringToFront(); + + mArcView.setVisibility(View.VISIBLE); + mEnterCloudPhoneButton.setVisibility(View.VISIBLE); + } + + offset = 0; + } + + private void showPhoneList(List phoneInfoList, boolean isRefreshData, boolean isRefreshView) { + if (mLayoutManager == null || mPhoneListAdapter == null || isRefreshView) { + prepareRecyclerView(); + } + + if (isRefreshData) { + mPhoneListAdapter.setNewInstance(phoneInfoList); + } else { + mPhoneListAdapter.addData(phoneInfoList); + } + + offset += phoneInfoList.size(); + } + + public void switchLayout() { + if (mPhoneListAdapter == null) return; + mViewType ++; + mViewType = mViewType % 2; + List phoneInfoList = mPhoneListAdapter.getData(); + if (mViewType == 0) { + mViewTypeIV.setImageResource(R.drawable.cas_view_list); + } else { + mAppBar.setExpanded(true,true); + mViewTypeIV.setImageResource(R.drawable.cas_view_carousel); + } + showPhoneList(phoneInfoList, true, true); + } + + public void showPhoneActionDialog(boolean isRestart, String phoneName, String message, String phoneId) { + if (mDialog == null || !mDialog.isShowing()) { + final View contentView = View.inflate(getActivity(), R.layout.cas_set_ui_level, null); + final CasCommonDialog.Builder builder = new CasCommonDialog.Builder(getActivity()); + CasCommonDialog.DialogClickListener dialogListener = new CasCommonDialog.DialogClickListener(); + + builder.setTitle(phoneName); + builder.setMessage(message); + builder.setContentView(contentView); + builder.setPositiveButton(getResources().getString(R.string.cas_phone_cancel_tip_message), dialogListener); + builder.setNegativeButton(getResources().getString(R.string.cas_phone_confirm_tip_message), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (isRestart) { + restartPhone(phoneId); + } else { + resetPhone(phoneId); + } + } + }); + + mDialog = builder.create(); + mDialog.setCancelable(true); + if (!getActivity().isFinishing()) { + mDialog.show(); + } + } + } + + private PhoneInfo phoneDetailToPhoneInfo(PhoneDetail phoneDetail) { + Phone phone = new Phone(); + phone.setPhoneId(phoneDetail.getPhoneId()); + phone.setPhoneName(phoneDetail.getPhoneName()); + phone.setAvailabilityZone(phoneDetail.getAvailabilityZone()); + phone.setCreateTime(phoneDetail.getCreateTime()); + phone.setUpdateTime(phoneDetail.getUpdateTime()); + phone.setPhoneModelName(phoneDetail.getPhoneModelName()); + phone.setImageId(phoneDetail.getImageId()); + phone.setImageVersion(phoneDetail.getImageVersion()); + phone.setImei(String.valueOf(phoneDetail.getImei())); + phone.setMetadata(phoneDetail.getMetadata()); + phone.setServerId(phoneDetail.getServerId()); + phone.setStatus(phoneDetail.getStatus()); + phone.setTrafficType(phoneDetail.getTrafficType()); + phone.setVncEnable("false"); + phone.setVolumeMode(phoneDetail.getVolumeMode()); + return new PhoneInfo(phone, EMPTY_STRING, selectedRegion); + } + + private void showPhoneDetail(PhoneDetail phoneDetail) { + + } + + private void showSearchView(View view) { + CustomDialog.build() + .setCustomView(new OnBindView(R.layout.cas_search_view) { + @Override + public void onBind(final CustomDialog dialog, View v) { + mSearchView = v.findViewById(R.id.search_view_popup_window); + + //设置搜索下拉框 + searchSpinner = v.findViewById(R.id.search_spinner); + List searchTypeList = Arrays.asList("名称", "服务器id", "云手机id"); + searchTypeSpinnerAdapter = new ArrayAdapter<>(mActivity, R.layout.spinner_item_search, searchTypeList); + searchTypeSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + searchSpinner.setAdapter(searchTypeSpinnerAdapter); + //设置搜索下拉框的监听器 + searchSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + selectedQueryType = i; + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + } + }); + searchSpinner.setSelection(selectedQueryType); + mSearchView.setQuery(queryContent, false); + mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + if (CasCommonUtils.isFastClick()) { + return false; + } + queryContent = s; + boolean isQueryContentValid = true; + if (selectedQueryType == 1 || selectedQueryType == 2) { + if (!CasCommonUtils.isValidUUID(queryContent)) { + isQueryContentValid = false; + } + } else { + if (!CasCommonUtils.isValidPhoneName(queryContent)) { + isQueryContentValid = false; + } + } + + if (!isQueryContentValid) { + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.query_intent_invalid); + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + return false; + } + + if (!queryContent.equals(EMPTY_STRING) && selectedQueryType == 2) { + getPhoneDetail(queryContent); + } else { + getUserPhoneList(true); + } + + List searchTypeList = Arrays.asList(new String[]{"名称", "服务器id", "云手机id", "状态"}); + mTVSearchContent.setText(searchTypeList.get(selectedQueryType) + ":" + queryContent); + mTVSearchContentClose.setVisibility(View.VISIBLE); + mSearchView.setQuery(queryContent, false); + mAppBar.setExpanded(true,true); + dialog.dismiss(); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + + }); + } + }) + .setAlign(CustomDialog.ALIGN.TOP_CENTER).setMaskColor(getResources().getColor(R.color.black60)) + .show(); + + } + + // 请求 + private void getUserInfo() { + String username = mUserCasRecord.getRecord(USERNAME); + if (username == null || username.isEmpty()) { + finishAndReLogin(true); + return; + } + String pass = CasCommonUtils.getEncryptPass(); + if (pass == null || pass.isEmpty()) { + finishAndReLogin(true); + return; + } + String iv = CasCommonUtils.getEncryptIV(); + if (iv == null || iv.isEmpty()) { + finishAndReLogin(true); + return; + } + String decryptPass = CasAESKeystoreUtils.decryptData(pass, iv); + + if (mUser == null) { + mUser = new User(username, + mUserCasRecord.getRecord(IAM_USERNAME), + mUserCasRecord.getHashMapRecord(TOKEN), + mUserCasRecord.getHashMapRecord(TOKEN_EXPIRE_TIME), + mUserCasRecord.getHashMapRecord(PROJECT_ID), + EMPTY_STRING); + } + IUserModel userModel = new com.huawei.cloudapp.model.direct.UserModel(); + UserPresenter userPresenter = new UserPresenter(this, userModel); + userPresenter.getUser(mUser, decryptPass, selectedRegion); + } + + private void getUserPhoneList(boolean isClearData) { + if (isClearData) { + offset = 0; + if (mPhoneListAdapter != null && !mPhoneListAdapter.getData().isEmpty()) { + mPhoneListAdapter.setNewInstance(null); + } + } + PhoneModel phoneModel = new PhoneModel(); + PhonePresenter phonePresenter = new PhonePresenter(this, phoneModel); + HashMap condition = new HashMap<>(); + + if (queryContent != null && !queryContent.isEmpty()) { + if (selectedQueryType == 0) { + condition.put(PHONE_NAME, queryContent); + } else if (selectedQueryType == 1) { + condition.put(SERVER_ID, queryContent); + } + } + + phonePresenter.getPhoneList(mUser, condition, selectedRegion, mUser.getUserProjectId().get(selectedRegion), offset, LIMIT); + } + + private void getPhoneDetail(String phoneId) { + PhoneModel phoneModel = new PhoneModel(); + PhonePresenter phonePresenter = new PhonePresenter(this, phoneModel); + phonePresenter.getPhoneDetailInfo(mUser, selectedRegion, mUser.getUserProjectId().get(selectedRegion), phoneId); + } + + private void restartPhone(String phoneId) { + PhoneModel phoneModel = new PhoneModel(); + PhonePresenter phonePresenter = new PhonePresenter(this, phoneModel); + phonePresenter.restartPhone(mUser, selectedRegion, + mUser.getUserProjectId().get(selectedRegion), + EMPTY_STRING, null, Collections.singletonList(phoneId)); + mDialog.dismiss(); + } + + private void resetPhone(String phoneId) { + PhoneModel phoneModel = new PhoneModel(); + PhonePresenter phonePresenter = new PhonePresenter(this, phoneModel); + phonePresenter.resetPhone(mUser, selectedRegion, + mUser.getUserProjectId().get(selectedRegion), + EMPTY_STRING, null, Collections.singletonList(phoneId)); + mDialog.dismiss(); + } + + // 连接 + private void startCloudPhoneActivity(PhoneInfo phoneInfo) { + if (CasCommonUtils.isFastClick() || !isLogin) { + return; + } + + Intent intent = new Intent(getActivity(), CasCloudPhoneActivity.class); + if (phoneInfo.getPhoneId().isEmpty()) { + return; + } + intent.putExtra(PHONE_ID, phoneInfo.getPhoneId()); + intent.putExtra(User.BUNDLE_KEY, mUser); + intent.putExtra(REGION_ID, selectedRegion); + startActivity(intent); + getActivity().overridePendingTransition(0, 0); + } + + private void finishAndReLogin(boolean isPrompt) { + if (isPrompt) { + //提示客户需要重新登陆 + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.user_info_invalid_need_login); + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + } + }); + } + getActivity().getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); + Intent intent = new Intent(getActivity(), CasCloudLoginActivity.class); + startActivity(intent); + getActivity().finish(); + } + + @Override + public boolean onBackPressed() { + if (mDialog != null && mDialog.isShowing()) { + mDialog.dismiss(); + return true; + } + if (!isReadyToExit) { + Toaster.show(R.string.cas_exit_app_confirmation); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + isReadyToExit = false; + } + }, 2000); + isReadyToExit = true; + return true; + } else { + return false; + } + } + + @Override + public void onResume() { + Log.e(TAG, "onResume: "); + super.onResume(); + } + + @Override + public void handleData(List list, int count) { + if (count == 0) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + //提示为空 + showPhoneList(new ArrayList<>(),true, false); + } + }); + } else if (list.size() == 0) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + //提示为空 + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.no_more_response); + params.style = new CustomToastStyle(R.layout.toast_info); + Toaster.show(params); + } + }); + } else if (((List) list).get(0) instanceof User) { + List users = (List) (List) list; + User user = users.get(0); + mUserCasRecord.setRecord(USERNAME, user.getUsername()); + mUserCasRecord.setRecord(IAM_USERNAME, user.getIamUsername()); + HashMap tokens = user.getUserToken(); + mUserCasRecord.setHashMapRecord(TOKEN, tokens); + HashMap tokenExpireTimes = user.getUserTokenExpireTime(); + mUserCasRecord.setHashMapRecord(TOKEN_EXPIRE_TIME, tokenExpireTimes); + HashMap projectIds = user.getUserProjectId(); + mUserCasRecord.setHashMapRecord(PROJECT_ID, projectIds); + mUserCasRecord.setRecord(SESSION_ID, user.getUserSessionId()); + mUser = user; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + getUserPhoneList(true); + } + }); + } else if (((List) list).get(0) instanceof PhoneInfo) { + List phones = (List) (List) list; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + boolean isRefreshData; + if (mPhoneListAdapter != null) { + isRefreshData = mPhoneListAdapter.getData().size() == 0; + } else { + isRefreshData = true; + } + showPhoneList(phones, isRefreshData, false); + if (mRefreshLayout != null) { + mRefreshLayout.finishRefresh(true).finishLoadMore(true); + } + } + }); + } else if (((List) list).get(0) instanceof PhoneDetail) { + List phoneDetail = (List) (List) list; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (selectedQueryType == 2) { + showPhoneList( + Collections.singletonList(phoneDetailToPhoneInfo(phoneDetail.get(0))), + true, false); + } else { + showPhoneDetail(phoneDetail.get(0)); + } + if (mRefreshLayout != null) { + mRefreshLayout.finishRefresh(true).finishLoadMore(true); + } + } + }); + } else if (((List) list).get(0) instanceof PhoneJobResponse) { + List phoneJobs = (List) (List) list; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + jobList.addAll(phoneJobs); + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.job_has_been_delivered); + params.style = new CustomToastStyle(R.layout.toast_success); + Toaster.show(params); + } + }); + } + } + + @Override + public void handleError(Exception e) { + Log.e(TAG, "handleError: " + e); + if (e instanceof CustomException.TokenExpireException) { + getUserInfo(); + } else if (e instanceof CustomException.LogInInfoErrorException + || e instanceof CustomException.FailedToLogInException ) { + finishAndReLogin(true); + } else { + String message; + if (e instanceof CustomException.FailedToGetPhoneListException) { + message = getResources().getString(R.string.failed_to_get_phone_list); + } else if (e instanceof CustomException.EmptyResponseFromServerException) { + message = getResources().getString(R.string.cas_phone_connect_server_fail_tip_message); + } else if (e instanceof CustomException.NoPermissionException) { + message = getResources().getString(R.string.no_permission); + }else if (e instanceof CustomException.OpRestrictedException) { + message = getResources().getString(R.string.op_restricted); + } else if (e instanceof CustomException.OpSuspendedException) { + message = getResources().getString(R.string.op_suspended); + } else if (e instanceof CustomException.OpUnverifiedException) { + message = getResources().getString(R.string.op_unverified); + } else if (e instanceof CustomException.DeliverJobFailedException) { + message = getResources().getString(R.string.job_deliver_failed); + } else if (e instanceof CustomException.ServerError) { + message = getResources().getString(R.string.service_internal_error); + } else if (e instanceof CustomException.ParamInvalidException || + e instanceof CustomException.PhoneNotFoundException || + e instanceof CustomException.JobNotFoundException || + e instanceof CustomException.ServerNotFoundException || + e instanceof CustomException.ResourceNotFoundException) { + message = getResources().getString(R.string.param_invalid); + } else { + message = getResources().getString(R.string.request_failed); + } + + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + ToastParams params = new ToastParams(); + params.text = message; + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + } + }); + } + } + + @Override + public void onLoadMore(@NonNull RefreshLayout refreshLayout) { + if (mUser == null || selectedRegion == null || selectedRegion.isEmpty() + || !mUser.getUserToken().containsKey(selectedRegion) + || !mUser.getUserTokenExpireTime().containsKey(selectedRegion) + || !mUser.getUserProjectId().containsKey(selectedRegion)) { + return; + } + Log.e(TAG, "onLoadMore: offset = " + offset); + if (!queryContent.equals(EMPTY_STRING) && selectedQueryType == 2) { + getPhoneDetail(queryContent); + } else { + getUserPhoneList(false); + } + } + + @Override + public void onRefresh(@NonNull RefreshLayout refreshLayout) { + if (mUser == null || selectedRegion == null || selectedRegion.isEmpty() + || !mUser.getUserToken().containsKey(selectedRegion) + || !mUser.getUserTokenExpireTime().containsKey(selectedRegion) + || !mUser.getUserProjectId().containsKey(selectedRegion)) { + return; + } + mPhoneListAdapter.setNewInstance(new ArrayList<>()); + if (!queryContent.equals(EMPTY_STRING) && selectedQueryType == 2) { + getPhoneDetail(queryContent); + } else { + getUserPhoneList(true); + } + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/fragment/mine/MineFragment.java b/app/src/main/java/com/huawei/cloudapp/ui/fragment/mine/MineFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..7f1f830177e9c0221c972220138075b75ab56cc3 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/fragment/mine/MineFragment.java @@ -0,0 +1,255 @@ +package com.huawei.cloudapp.ui.fragment.mine; + +import static android.content.Context.MODE_PRIVATE; +import static com.huawei.cloudapp.utils.CasConstantsUtil.COMMON; +import static com.huawei.cloudapp.utils.CasConstantsUtil.IAM_USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PROJECT_ID; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN; +import static com.huawei.cloudapp.utils.CasConstantsUtil.TOKEN_EXPIRE_TIME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USERNAME; +import static com.huawei.cloudapp.utils.CasConstantsUtil.USER_INFO; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.hjq.toast.ToastParams; +import com.hjq.toast.Toaster; +import com.hjq.toast.style.CustomToastStyle; +import com.huawei.cloudapp.R; +import com.huawei.cloudapp.common.CasCommonDialog; +import com.huawei.cloudapp.common.CasRecord; +import com.huawei.cloudapp.model.bean.User; +import com.huawei.cloudapp.ui.activity.CasCloudLoginActivity; +import com.huawei.cloudapp.ui.activity.mine.MineAboutActivity; +import com.huawei.cloudapp.ui.activity.mine.MineGuideActivity; +import com.huawei.cloudapp.ui.activity.mine.MineQuestionActivity; +import com.huawei.cloudapp.ui.common.ButtonTouchStyleListener; +import com.huawei.cloudapp.ui.fragment.CloudPhoneFragment; +import com.huawei.cloudapp.utils.CasCommonUtils; + +public class MineFragment extends CloudPhoneFragment { + + private static final String TAG = "MineFragment"; + private CasRecord mUserCasRecord; + private User mUser; + private boolean isLogin; + private CasCommonDialog mDialog; + private LinearLayout mLayout; + private CasRecord mCommonCasRecord; + private Button logoutButton; + private boolean isReadyToExit = false; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + Log.e(TAG, "onCreate: "); + super.onCreate(savedInstanceState); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + Log.e(TAG, "onCreateView: "); + View view = inflater.inflate(R.layout.fragment_mine, container, false); + getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + mUserCasRecord = new CasRecord(getActivity().getSharedPreferences(USER_INFO, MODE_PRIVATE)); + String username = mUserCasRecord.getRecord(USERNAME); + if (username == null || username.isEmpty()) { + finishAndReLogin(true); + } else { + mUser = new User(username, + mUserCasRecord.getRecord(IAM_USERNAME), + mUserCasRecord.getHashMapRecord(TOKEN), + mUserCasRecord.getHashMapRecord(TOKEN_EXPIRE_TIME), + mUserCasRecord.getHashMapRecord(PROJECT_ID), + ""); + isLogin = true; + } + return view; + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + Log.e(TAG, "onViewCreated: "); + super.onViewCreated(view, savedInstanceState); + mLayout = view.findViewById(R.id.fragment_mine); + mCommonCasRecord = new CasRecord(view.getContext().getSharedPreferences(COMMON, MODE_PRIVATE)); + + // 圆形头像 + ImageView headImage = view.findViewById(R.id.head); + Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.head); + Bitmap bitmap2 = CasCommonUtils.makeBitmapSquare(bitmap1, 120); + RoundedBitmapDrawable roundImg = RoundedBitmapDrawableFactory.create(getResources(), bitmap2); + roundImg.setAntiAlias(true); + roundImg.setCornerRadius(bitmap2.getWidth() / 2); + headImage.setImageDrawable(roundImg); + + RelativeLayout aboutLinear = view.findViewById(R.id.mine_about_linear); + aboutLinear.setOnTouchListener(new ButtonTouchStyleListener()); + aboutLinear.setOnClickListener(new SwitchFragmentClickListener()); + + RelativeLayout guideLinear = view.findViewById(R.id.mine_guide_linear); + guideLinear.setOnTouchListener(new ButtonTouchStyleListener()); + guideLinear.setOnClickListener(new SwitchFragmentClickListener()); + + RelativeLayout questionLinear = view.findViewById(R.id.mine_question_linear); + questionLinear.setOnTouchListener(new ButtonTouchStyleListener()); + questionLinear.setOnClickListener(new SwitchFragmentClickListener()); + + logoutButton = view.findViewById(R.id.logout); + logoutButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onLogOut(); + } + }); + + fillUserInfo(view); + + fillSdkVersion(view, getContext()); + + } + + private void fillUserInfo(@NonNull View view) { + if (mUser != null) { + TextView iamUserNameTextView = view.findViewById(R.id.iam_user_name); + iamUserNameTextView.setText(mUser.getIamUsername()); + + TextView userNameTextView = view.findViewById(R.id.user_name); + userNameTextView.setText(mUser.getUsername()); + } + } + + private void fillSdkVersion(View view, Context context) { + TextView sdkTextView = view.findViewById(R.id.sdk_version); + sdkTextView.setText(CasCommonUtils.getApkVersion(context)); + } + + private void finishAndReLogin(boolean isPrompt) { + if (isPrompt) { + //提示客户需要重新登陆 + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + ToastParams params = new ToastParams(); + params.text = getResources().getString(R.string.user_info_invalid_need_login); + params.style = new CustomToastStyle(R.layout.toast_error); + Toaster.show(params); + } + }); + } + getActivity().getSharedPreferences(USER_INFO, MODE_PRIVATE).edit().clear().apply(); + Intent intent = new Intent(getActivity(), CasCloudLoginActivity.class); + startActivity(intent); + getActivity().finish(); + } + + @Override + public void onResume() { + Log.e(TAG, "onResume: "); + super.onResume(); + } + + @Override + public void onDestroyView() { + Log.e(TAG, "onDestroyView: "); + super.onDestroyView(); + } + + private void onLogOut() { + if (!isLogin) { + finishAndReLogin(false); + } else { + String name = mUser.getUsername(); + if (!mUser.getIamUsername().isEmpty()) { + name = mUser.getIamUsername(); + } + showLogoutUserDialog(name); + } + } + + public void showLogoutUserDialog(String username) { + if (mDialog == null || !mDialog.isShowing()) { + final View contentView = View.inflate(getContext(), R.layout.cas_set_ui_level, null); + final CasCommonDialog.Builder builder = new CasCommonDialog.Builder(getContext()); + CasCommonDialog.DialogClickListener dialogListener = new CasCommonDialog.DialogClickListener(); + + builder.setTitle(username); + builder.setMessage(getResources().getString(R.string.is_exit_account)); + builder.setContentView(contentView); + builder.setPositiveButton(getResources().getString(R.string.cas_phone_cancel_tip_message), dialogListener); + builder.setNegativeButton(getResources().getString(R.string.cas_phone_quit_app_tip_message), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finishAndReLogin(false); + } + }); + + mDialog = builder.create(); + mDialog.setCancelable(true); + if (!getActivity().isFinishing()) { + mDialog.show(); + } + } + } + + @Override + public boolean onBackPressed() { + if (mDialog != null && mDialog.isShowing()) { + mDialog.dismiss(); + return true; + } + if (!isReadyToExit) { + Toaster.show(R.string.cas_exit_app_confirmation); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + isReadyToExit = false; + } + }, 2000); + isReadyToExit = true; + return true; + } else { + return false; + } + } + + class SwitchFragmentClickListener implements View.OnClickListener { + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.mine_about_linear: + startActivity(new Intent(getActivity(), MineAboutActivity.class)); + break; + case R.id.mine_guide_linear: + startActivity(new Intent(getActivity(), MineGuideActivity.class)); + break; + case R.id.mine_question_linear: + startActivity(new Intent(getActivity(), MineQuestionActivity.class)); + break; + } + } + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/ui/surface/CasArcView.java b/app/src/main/java/com/huawei/cloudapp/ui/views/CasArcView.java similarity index 98% rename from app/src/main/java/com/huawei/cloudapp/ui/surface/CasArcView.java rename to app/src/main/java/com/huawei/cloudapp/ui/views/CasArcView.java index 87d4490a96c0915ed194908ba790ee61b958aa96..d4ce017c3d25872a6f03283e425ad4063f62c7d4 100644 --- a/app/src/main/java/com/huawei/cloudapp/ui/surface/CasArcView.java +++ b/app/src/main/java/com/huawei/cloudapp/ui/views/CasArcView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.huawei.cloudapp.ui.surface; +package com.huawei.cloudapp.ui.views; import android.content.Context; import android.content.res.TypedArray; diff --git a/app/src/main/java/com/huawei/cloudapp/ui/views/MaterialLoginView.java b/app/src/main/java/com/huawei/cloudapp/ui/views/MaterialLoginView.java new file mode 100644 index 0000000000000000000000000000000000000000..8aaa039364d523fa69bb8f98be064d4c1f03ca31 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/ui/views/MaterialLoginView.java @@ -0,0 +1,121 @@ +package com.huawei.cloudapp.ui.views; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.google.android.material.checkbox.MaterialCheckBox; +import com.google.android.material.textfield.TextInputLayout; +import com.huawei.cloudapp.R; + +public class MaterialLoginView extends FrameLayout { + + private static final String TAG = MaterialLoginView.class.getSimpleName(); + + public interface LoginViewListener { + void onLogin(TextInputLayout loginUser, TextInputLayout loginIamUser, TextInputLayout loginPass, boolean isUseIam); + } + + private LoginViewListener listener; + private MaterialCheckBox checkBox; + + public MaterialLoginView(Context context) { + this(context, null); + } + + public MaterialLoginView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public MaterialLoginView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.login_view, this, true); + + TypedArray a = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.MaterialLoginView, + 0, 0); + + TextView loginTitle = findViewById(R.id.login_title); + final TextInputLayout loginUser = findViewById(R.id.login_user); + final TextInputLayout loginPass = findViewById(R.id.login_pass); + final TextInputLayout loginIamUser = findViewById(R.id.login_iam_user); + + checkBox = findViewById(R.id.is_use_iam); + final boolean[] isUseIam = {false}; + final String[] mode = {""}; + + checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + if (b) { + loginIamUser.setVisibility(VISIBLE); + } else { + loginIamUser.setVisibility(GONE); + } + isUseIam[0] = b; + } + }); + + TextView loginBtn = findViewById(R.id.login_btn); + findViewById(R.id.login_btn).setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onLogin(loginUser, loginIamUser, loginPass, isUseIam[0]); + } + } + }); + + try { + String string = a.getString(R.styleable.MaterialLoginView_loginTitle); + if (string != null) { + loginTitle.setText(string); + } + + string = a.getString(R.styleable.MaterialLoginView_loginHint); + if (string != null) { + loginUser.setHint(string); + } + + string = a.getString(R.styleable.MaterialLoginView_loginPasswordHint); + if (string != null) { + loginPass.setHint(string); + } + + string = a.getString(R.styleable.MaterialLoginView_loginActionText); + if (string != null) { + loginBtn.setText(string); + } + + int color = a.getColor(R.styleable.MaterialLoginView_loginTextColor, ContextCompat.getColor(getContext(), R.color.material_login_login_text_color)); + loginUser.getEditText().setTextColor(color); + loginIamUser.getEditText().setTextColor(color); + loginPass.getEditText().setTextColor(color); + checkBox.setChecked(true); + } finally { + a.recycle(); + } + } + + public void setListener(LoginViewListener listener) { + this.listener = listener; + } + + public void setIamEnable(boolean enable) { + int visibility = enable ? VISIBLE : GONE; + checkBox.setVisibility(visibility); + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/utils/CasAESKeystoreUtils.java b/app/src/main/java/com/huawei/cloudapp/utils/CasAESKeystoreUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..225f96951b24103ac4a8b92d1066df96db87d858 --- /dev/null +++ b/app/src/main/java/com/huawei/cloudapp/utils/CasAESKeystoreUtils.java @@ -0,0 +1,123 @@ +package com.huawei.cloudapp.utils; + +import static com.huawei.cloudapp.utils.CasConstantsUtil.ENCRYPT_IV; +import static com.huawei.cloudapp.utils.CasConstantsUtil.PASSWORD; + +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; +import android.util.Base64; +import android.util.Log; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableEntryException; +import java.security.cert.CertificateException; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.HashMap; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; + +public class CasAESKeystoreUtils { + private static String TAG = "CasAESKeystoreUtils"; + private static String TRANSFORMATION = "AES/GCM/NoPadding"; + private static final String ALIAS = "keyAlias"; + + private static void createKey() { + final KeyGenerator keyGenerator; + AlgorithmParameterSpec spec = null; + try { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); + Calendar start = new GregorianCalendar(); + Calendar end = new GregorianCalendar(); + end.add(Calendar.YEAR, 10); + spec = new KeyGenParameterSpec.Builder(ALIAS, + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .setCertificateNotBefore(start.getTime()) + .setCertificateNotAfter(end.getTime()) + .build(); + keyGenerator.init(spec); + keyGenerator.generateKey(); + } + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + Log.e(TAG, "encryptData: ", e); + } + } + + public static HashMap encryptData(String data) { + if (!hasAliasKey()) { + createKey(); + } + try { + KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null); + SecretKey secretKey = secretKeyEntry.getSecretKey(); + //KeyGenParameterSpecs中设置的block模式是KeyProperties.BLOCK_MODE_GCM,所以这里只能使用这个模式解密数据。 + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + HashMap encryptResult = new HashMap<>(); + encryptResult.put(PASSWORD, Base64.encodeToString(cipher.doFinal(data.getBytes()), Base64.NO_WRAP)); + encryptResult.put(ENCRYPT_IV, Base64.encodeToString(cipher.getIV(), Base64.NO_WRAP)); + return encryptResult; + } catch (KeyStoreException | IOException | NoSuchAlgorithmException | + CertificateException | InvalidKeyException | UnrecoverableEntryException | + NoSuchPaddingException | BadPaddingException | + IllegalBlockSizeException | NullPointerException e) { + Log.e(TAG, "encryptData: ", e); + } + return null; + } + + public static String decryptData(String ciphertext, String encryptIv) { + if (!hasAliasKey()) { + createKey(); + } + try { + KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null); + SecretKey secretKey = secretKeyEntry.getSecretKey(); + //KeyGenParameterSpecs中设置的block模式是KeyProperties.BLOCK_MODE_GCM,所以这里只能使用这个模式解密数据。 + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, Base64.decode(encryptIv, Base64.NO_WRAP)); + cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec); + return new String(cipher.doFinal(Base64.decode(ciphertext, Base64.NO_WRAP))); + } catch (InvalidKeyException | InvalidAlgorithmParameterException | IOException | + CertificateException | NoSuchAlgorithmException | UnrecoverableEntryException | + NoSuchPaddingException | KeyStoreException | + BadPaddingException | IllegalBlockSizeException e) { + Log.e(TAG, "decryptData: ", e); + } + return ""; + } + + private static boolean hasAliasKey() { + try { + KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + KeyStore.Entry keyEntry = keyStore.getEntry(ALIAS, null); + if (null != keyEntry) { + return true; + } + } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableEntryException e) { + Log.e(TAG, "hasAliasKey: ", e); + } + return false; + } +} diff --git a/app/src/main/java/com/huawei/cloudapp/utils/CasCommonUtils.java b/app/src/main/java/com/huawei/cloudapp/utils/CasCommonUtils.java index 5c938389ba6377f6f1921dbc01c77b0dfe3da978..3665fdcb62e91179e21667ac718c15f6aef6da5a 100644 --- a/app/src/main/java/com/huawei/cloudapp/utils/CasCommonUtils.java +++ b/app/src/main/java/com/huawei/cloudapp/utils/CasCommonUtils.java @@ -1,5 +1,12 @@ package com.huawei.cloudapp.utils; +import static com.huawei.cloudapp.utils.CasConstantsUtil.EMPTY_STRING; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Matrix; import android.media.MediaCodecList; import android.media.MediaFormat; import android.os.SystemClock; @@ -7,19 +14,34 @@ import android.os.SystemClock; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; +import com.huawei.cloudapp.BuildConfig; + import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; public class CasCommonUtils { - private static final long CLICK_INTERVAL = 1500; + + /** + * 判断32位uuid + */ + private static final Pattern PATTERN_UUID = Pattern.compile("[a-f0-9]{32}"); + + /** + * phone名 校验规则 + */ + private static final Pattern NAME_PATTERN = Pattern.compile("^[-_a-zA-Z0-9\u4e00-\u9fa5]{1,60}$"); + private static final long CLICK_INTERVAL = 1000; private static long lastClickTime = 0; private static long[] mHits; private static Gson gson = new Gson(); private static Type typeMap = new TypeToken>(){}.getType(); private static Type typeList = new TypeToken>>(){}.getType(); + private static String encryptPass = ""; + private static String encryptIV = ""; public static boolean isFastClick() { long currentTime = System.currentTimeMillis(); @@ -52,7 +74,7 @@ public class CasCommonUtils { } } - public static boolean onDisplaySettingButton() { + public static boolean onJumpToDebugView() { if (mHits == null) { mHits = new long[5]; } @@ -72,7 +94,73 @@ public class CasCommonUtils { MediaFormat.createVideoFormat(mimeType, 1920, 1080)) != null; } + public static boolean isDirectMode() { + return BuildConfig.IS_DIRECT_MODE; + } + public static String getManagementUrl() { return CasConstantsUtil.MANAGEMENT_PROD_ENV_URL; } + + public static String getEncryptPass() { + return encryptPass; + } + + public static void setEncryptPass(String pass) { + CasCommonUtils.encryptPass = pass; + } + + public static String getEncryptIV() { + return encryptIV; + } + + public static void setEncryptIV(String encryptIV) { + CasCommonUtils.encryptIV = encryptIV; + } + + public static int dip2px(Context context, float dp) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + public static boolean isValidUUID(String uuid) { + return !isStringEmpty(uuid) && PATTERN_UUID.matcher(uuid).matches(); + } + + public static boolean isValidPhoneName(String phoneName) { + return !isStringEmpty(phoneName) && NAME_PATTERN.matcher(phoneName).matches(); + } + + public static boolean isStringEmpty(String str) { + return str == null || str.length() == 0; + } + + public static String getApkVersion(Context context) { + if (context == null) { + return EMPTY_STRING; + } + try { + // getPackageName()是当前类的包名,0代表是获取版本信息 + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + return packageInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return EMPTY_STRING; + } + + public static Bitmap makeBitmapSquare(Bitmap oldBitmap, int newWidth) { + Bitmap newBitmap; + if (oldBitmap.getWidth() > oldBitmap.getHeight()) { + newBitmap = Bitmap.createBitmap(oldBitmap, oldBitmap.getWidth() / 2 - oldBitmap.getHeight() / 2, 0, oldBitmap.getHeight(), oldBitmap.getHeight()); + } else { + newBitmap = Bitmap.createBitmap(oldBitmap, 0, oldBitmap.getHeight() / 2 - oldBitmap.getWidth() / 2, oldBitmap.getWidth(), oldBitmap.getWidth()); + } + int width = newBitmap.getWidth(); + float scaleWidth = ((float) newWidth) / width; + Matrix matrix = new Matrix(); + matrix.postScale(scaleWidth, scaleWidth); + newBitmap = Bitmap.createBitmap(newBitmap, 0, 0, width, width, matrix, true); + return newBitmap; + } } 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 070934ea6b3a1642629576b5f49f2446c3264b78..3ecbdc9b5457b89a066254a142b0fd5b2e4e8c5c 100644 --- a/app/src/main/java/com/huawei/cloudapp/utils/CasConstantsUtil.java +++ b/app/src/main/java/com/huawei/cloudapp/utils/CasConstantsUtil.java @@ -16,7 +16,9 @@ package com.huawei.cloudapp.utils; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.regex.Pattern; @@ -27,14 +29,22 @@ public class CasConstantsUtil { public static final String USERNAME = "username"; + public static final String IAM_USERNAME = "iam_username"; + public static final String PASSWORD = "password"; + public static final String ENCRYPT_IV = "iv"; + public static final String ERROR_CODE = "errorCode"; public static final String ERROR_MSG = "errorMsg"; public static final String TOKEN = "token"; + public static final String TOKEN_EXPIRE_TIME = "token_expire_time"; + + public static final String PROJECT_ID = "project_id"; + public static final String ORIENTATION = "orientation"; public static final String MEDIA_CONFIG = "media_config"; @@ -47,6 +57,17 @@ public class CasConstantsUtil { public static final String CLIENT_TYPE = "client_type"; + public static final String CLIENT_MODE = "client_mode"; + + public static final String ERROR = "error"; + + public static final String CODE = "code"; + + public static final String MESSAGE = "message"; + + public static final String X_SUBJECT_TOKEN = "X-Subject-Token"; + public static final String X_AUTH_TOKEN = "X-Auth-Token"; + /** * cph:ip */ @@ -92,11 +113,17 @@ public class CasConstantsUtil { public static final String AES_KEY = "aes_key"; /** - * auth th + * auth ts *

authentication timestamp

*/ public static final String AUTH_TS = "auth_ts"; + /** + * timestamp + *

timestamp

+ */ + public static final String TIMESTAMP = "timestamp"; + /** * userid */ @@ -176,6 +203,8 @@ public class CasConstantsUtil { * user_info */ public static final String USER_INFO = "user_info"; + public static final String COMMON = "common"; + public static final String SELECTED_REGION_POSITION = "selected_region_position"; public static final String FRAME_TYPE_H265 = "h265"; public static final String FRAME_TYPE_H264 = "h264"; @@ -189,6 +218,9 @@ public class CasConstantsUtil { public static final String DEBUG_MODE = "debug_mode"; + 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_PROD_ENV_URL = "https://139.9.146.101:18000"; public static final String PHONE = "phone"; @@ -197,18 +229,59 @@ public class CasConstantsUtil { public static final String ALLOCATION = "allocate"; public static final String USER = "user"; public static final String LOGIN = "login"; + public static final String DIRECT = "direct"; + public static final String MANAGEMENT = "management"; + + public static final String SERVER_ID = "server_id"; + public static final String STATUS = "status"; + + public static final String EMPTY_STRING = ""; + public static final String ENTER_STRING = "\n"; + + + + public static final List REGION_NAME; + static { + REGION_NAME = new ArrayList<>(); + REGION_NAME.add("ap-southeast-1"); + REGION_NAME.add("ap-southeast-3"); + REGION_NAME.add("cn-east-2"); + REGION_NAME.add("cn-east-3"); + REGION_NAME.add("cn-north-4"); + REGION_NAME.add("cn-south-1"); + REGION_NAME.add("cn-southwest-2"); + REGION_NAME.add("ru-northwest-2"); + } public static final Map REGION_INFO; static { - REGION_INFO = new HashMap<>(); - REGION_INFO.put("ap-southeast-1", "中国-香港"); - REGION_INFO.put("ap-southeast-3", "亚太-新加坡"); - REGION_INFO.put("cn-east-2", "华东-上海二"); - REGION_INFO.put("cn-east-3", "华东-上海一"); - REGION_INFO.put("cn-north-4", "华北-北京四"); - REGION_INFO.put("cn-south-1", "华南-广州"); - REGION_INFO.put("cn-southwest-2", "西南-贵阳一"); - REGION_INFO.put("ru-northwest-2", "俄罗斯-莫斯科二"); + REGION_INFO = new LinkedHashMap<>(); + REGION_INFO.put(REGION_NAME.get(0), "香港"); + REGION_INFO.put(REGION_NAME.get(1), "新加坡"); + REGION_INFO.put(REGION_NAME.get(2), "上海二"); + REGION_INFO.put(REGION_NAME.get(3), "上海一"); + REGION_INFO.put(REGION_NAME.get(4), "北京四"); + REGION_INFO.put(REGION_NAME.get(5), "广州"); + REGION_INFO.put(REGION_NAME.get(6), "贵阳一"); + REGION_INFO.put(REGION_NAME.get(7), "莫斯科二"); + } + + public static final Map PHONE_STATUS; + static { + PHONE_STATUS = new LinkedHashMap<>(); + PHONE_STATUS.put(0, "所有状态"); + PHONE_STATUS.put(1, "创建中"); + PHONE_STATUS.put(2, "运行中"); + PHONE_STATUS.put(3, "重置中"); + PHONE_STATUS.put(4, "重启中"); + PHONE_STATUS.put(6, "冻结"); + PHONE_STATUS.put(7, "正在关机"); + PHONE_STATUS.put(8, "已关机"); + PHONE_STATUS.put(-5, "重置失败"); + PHONE_STATUS.put(-6, "重启失败"); + PHONE_STATUS.put(-7, "手机异常"); + PHONE_STATUS.put(-8, "创建失败"); + PHONE_STATUS.put(-9, "关机失败"); } } diff --git a/app/src/main/java/com/huawei/cloudapp/utils/CasHttpUtils.java b/app/src/main/java/com/huawei/cloudapp/utils/CasHttpUtils.java index 3c4323e8deb80187ed09fed265f4b0faab6d915a..836c0d089c623a5203327d9056d8397e72033edc 100644 --- a/app/src/main/java/com/huawei/cloudapp/utils/CasHttpUtils.java +++ b/app/src/main/java/com/huawei/cloudapp/utils/CasHttpUtils.java @@ -6,9 +6,12 @@ import android.util.Log; import androidx.annotation.NonNull; +import com.google.gson.Gson; + import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import java.util.List; import java.util.Map; import javax.net.ssl.SSLContext; @@ -18,6 +21,7 @@ import javax.net.ssl.X509TrustManager; import okhttp3.Call; import okhttp3.Callback; +import okhttp3.FormBody; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -28,11 +32,6 @@ public class CasHttpUtils { public static final String TAG = "CasHttpUtils"; public static final MediaType JSON = MediaType.get("application/json"); - static OkHttpClient client = new OkHttpClient(); - - public static void post(String url, String json, Handler handler, int msgCode) { - post(url, null, json, handler, msgCode); - } public static void post(String url, Map header, String json, Handler handler, int msgCode) { RequestBody body = RequestBody.create(json, JSON); @@ -68,6 +67,37 @@ public class CasHttpUtils { }); } + public static void post(String url, Map header, String bodyStr, Callback callback) { + RequestBody body = RequestBody.create(bodyStr, JSON); + Request.Builder builder = new Request.Builder(); + + if (header != null && !header.isEmpty()) { + for (Map.Entry entry : header.entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + } + + Request request = builder.url(url) + .post(body) + .build(); + + OKHttpClientBuilder.buildOKHttpClient().build().newCall(request).enqueue(callback); + } + + public static void get(String url, Map header, Callback callback) { + Request.Builder builder = new Request.Builder(); + if (header != null && !header.isEmpty()) { + for (Map.Entry entry : header.entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + } + + Request request = builder.url(url) + .build(); + + OKHttpClientBuilder.buildOKHttpClient().build().newCall(request).enqueue(callback); + } + public static class OKHttpClientBuilder { public static OkHttpClient.Builder buildOKHttpClient() { try { @@ -106,6 +136,4 @@ public class CasHttpUtils { } } - - } diff --git a/app/src/main/res/anim/slide_center.xml b/app/src/main/res/anim/slide_center.xml new file mode 100644 index 0000000000000000000000000000000000000000..b7c9c0202a7e429cf4cc28a0b1649b948967e6f1 --- /dev/null +++ b/app/src/main/res/anim/slide_center.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_left.xml b/app/src/main/res/anim/slide_in_left.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd2f0abd4e732b9a6b3481a7dfd3a80c481d8723 --- /dev/null +++ b/app/src/main/res/anim/slide_in_left.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000000000000000000000000000000000000..302bdac26b879c0ecf7200894a9b859862447898 --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml new file mode 100644 index 0000000000000000000000000000000000000000..1274f23afabc9755f3670a3cbec70f77b41e8c27 --- /dev/null +++ b/app/src/main/res/anim/slide_out_left.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml new file mode 100644 index 0000000000000000000000000000000000000000..a820739e370b18bfbeb04e9f8171c956134a625b --- /dev/null +++ b/app/src/main/res/anim/slide_out_right.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cae_view_back.xml b/app/src/main/res/drawable/cae_view_back.xml new file mode 100644 index 0000000000000000000000000000000000000000..da97870780e66fdb41248f53a6ea2b1758c1bf4f --- /dev/null +++ b/app/src/main/res/drawable/cae_view_back.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cae_view_enter.xml b/app/src/main/res/drawable/cae_view_enter.xml new file mode 100644 index 0000000000000000000000000000000000000000..6451cd0869db7c946cd98d97011622c257b70e10 --- /dev/null +++ b/app/src/main/res/drawable/cae_view_enter.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_bg_round_white.xml b/app/src/main/res/drawable/cas_bg_round_white.xml index e3a3e6ccb468d638fcd055965d0f16ac460cf725..802f714caa4121d7bb462d4f64c80e7179c9aa8f 100644 --- a/app/src/main/res/drawable/cas_bg_round_white.xml +++ b/app/src/main/res/drawable/cas_bg_round_white.xml @@ -1,6 +1,5 @@ - \ No newline at end of file diff --git a/app/src/main/res/drawable/cas_close.xml b/app/src/main/res/drawable/cas_close.xml new file mode 100644 index 0000000000000000000000000000000000000000..70db409b33846063632c78389654a409543d882f --- /dev/null +++ b/app/src/main/res/drawable/cas_close.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_cloud_phone.xml b/app/src/main/res/drawable/cas_cloud_phone.xml new file mode 100644 index 0000000000000000000000000000000000000000..e8f4fb104c0f5506d3837b857e051d2dbf836536 --- /dev/null +++ b/app/src/main/res/drawable/cas_cloud_phone.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_explore.xml b/app/src/main/res/drawable/cas_explore.xml new file mode 100644 index 0000000000000000000000000000000000000000..4aa486a301a1714f99cfa35fe11b696a1b8da32c --- /dev/null +++ b/app/src/main/res/drawable/cas_explore.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_guide_chapter_1.png b/app/src/main/res/drawable/cas_guide_chapter_1.png new file mode 100644 index 0000000000000000000000000000000000000000..dd263308c58ce8af70e6974126416b79acb76d9c Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_1.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_2_1.png b/app/src/main/res/drawable/cas_guide_chapter_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9bffa01c35a87c2630e0efb9811aed1cf809b4eb Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_2_1.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_2_2.png b/app/src/main/res/drawable/cas_guide_chapter_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..9226d8d8114e53c5cdfc82e09e27d95eb95a14a6 Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_2_2.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_2_3.png b/app/src/main/res/drawable/cas_guide_chapter_2_3.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7d0fe6b8a76f42d2148cdd7971a1e34693c0ba Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_2_3.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_2_4.png b/app/src/main/res/drawable/cas_guide_chapter_2_4.png new file mode 100644 index 0000000000000000000000000000000000000000..14de222e02e2be9d35b6224728dfd841f7e035e7 Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_2_4.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_2_5.png b/app/src/main/res/drawable/cas_guide_chapter_2_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2394082d6bb7b48a1a03142ecc7afd9edfedee37 Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_2_5.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_3.png b/app/src/main/res/drawable/cas_guide_chapter_3.png new file mode 100644 index 0000000000000000000000000000000000000000..63d157898422510a0f5c465ce66c161325fc854e Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_3.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_4.png b/app/src/main/res/drawable/cas_guide_chapter_4.png new file mode 100644 index 0000000000000000000000000000000000000000..0750ce1954417731bfa15f0bbef35ed53a94791e Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_4.png differ diff --git a/app/src/main/res/drawable/cas_guide_chapter_5.png b/app/src/main/res/drawable/cas_guide_chapter_5.png new file mode 100644 index 0000000000000000000000000000000000000000..beb07879ee54885d562f3fad3ffb41c320db1884 Binary files /dev/null and b/app/src/main/res/drawable/cas_guide_chapter_5.png differ diff --git a/app/src/main/res/drawable/cas_line_border_black.xml b/app/src/main/res/drawable/cas_line_border_black.xml new file mode 100644 index 0000000000000000000000000000000000000000..726e1155d3675e9958f2871634b977834b6e4c79 --- /dev/null +++ b/app/src/main/res/drawable/cas_line_border_black.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cas_line_border_gray.xml b/app/src/main/res/drawable/cas_line_border_gray.xml new file mode 100644 index 0000000000000000000000000000000000000000..7908dab3a0ccf7f4e63d3d171e5c13ceea1e8520 --- /dev/null +++ b/app/src/main/res/drawable/cas_line_border_gray.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cas_line_border_primary.xml b/app/src/main/res/drawable/cas_line_border_primary.xml new file mode 100644 index 0000000000000000000000000000000000000000..ffc5f061caca84ab60c8eb09ee3174b35c657352 --- /dev/null +++ b/app/src/main/res/drawable/cas_line_border_primary.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cas_more.xml b/app/src/main/res/drawable/cas_more.xml new file mode 100644 index 0000000000000000000000000000000000000000..29f548a7bb8429b2128dc581fe24086ae1fc1dae --- /dev/null +++ b/app/src/main/res/drawable/cas_more.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_phone.xml b/app/src/main/res/drawable/cas_phone.xml new file mode 100644 index 0000000000000000000000000000000000000000..96619df637c33ff22e5719d55126d7ffeb962b79 --- /dev/null +++ b/app/src/main/res/drawable/cas_phone.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_search.xml b/app/src/main/res/drawable/cas_search.xml new file mode 100644 index 0000000000000000000000000000000000000000..230d170eb85fb5f1b8f557f8214f0d8fb672a69c --- /dev/null +++ b/app/src/main/res/drawable/cas_search.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/cas_status_error.xml b/app/src/main/res/drawable/cas_status_error.xml new file mode 100644 index 0000000000000000000000000000000000000000..14cddbbcaba97e4bee68ff93b8c89225ec0d54ef --- /dev/null +++ b/app/src/main/res/drawable/cas_status_error.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_status_normal.xml b/app/src/main/res/drawable/cas_status_normal.xml new file mode 100644 index 0000000000000000000000000000000000000000..6a64c49e0e042fcfd24e5c47a01dfa55fdbe3efe --- /dev/null +++ b/app/src/main/res/drawable/cas_status_normal.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_status_process.xml b/app/src/main/res/drawable/cas_status_process.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f5fa473f4ec38669844a407e81bb96526e2389c --- /dev/null +++ b/app/src/main/res/drawable/cas_status_process.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_status_shutdown.xml b/app/src/main/res/drawable/cas_status_shutdown.xml new file mode 100644 index 0000000000000000000000000000000000000000..8253241c492b6bf5e53c951cc7a38e9eb2fb1069 --- /dev/null +++ b/app/src/main/res/drawable/cas_status_shutdown.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_view_carousel.xml b/app/src/main/res/drawable/cas_view_carousel.xml new file mode 100644 index 0000000000000000000000000000000000000000..c922e465154f1c4ee86dbb2aaad7952aab62214b --- /dev/null +++ b/app/src/main/res/drawable/cas_view_carousel.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_view_grid.xml b/app/src/main/res/drawable/cas_view_grid.xml new file mode 100644 index 0000000000000000000000000000000000000000..fab556aeabe5b211c952e549930c7ea17539f901 --- /dev/null +++ b/app/src/main/res/drawable/cas_view_grid.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/cas_view_list.xml b/app/src/main/res/drawable/cas_view_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..a3ca550376e6caea38c4e9409d29ef227fdc1390 --- /dev/null +++ b/app/src/main/res/drawable/cas_view_list.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/desktop.png b/app/src/main/res/drawable/desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..2aec2f8ad609609000280caa7e821f56b1f87d02 Binary files /dev/null and b/app/src/main/res/drawable/desktop.png differ diff --git a/app/src/main/res/drawable/head.jpg b/app/src/main/res/drawable/head.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b0567a98c26223d2db9948a6e1c67c398616e210 Binary files /dev/null and b/app/src/main/res/drawable/head.jpg differ diff --git a/app/src/main/res/drawable/ic_home_black_24dp.xml b/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8bb0b55633d3e41228e9e285149af5f1d839d08 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/login_back.xml b/app/src/main/res/drawable/login_back.xml new file mode 100644 index 0000000000000000000000000000000000000000..57855d38d8740aef7a4ecf1ae066c8b0f433f342 --- /dev/null +++ b/app/src/main/res/drawable/login_back.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/main_background.xml b/app/src/main/res/drawable/main_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..c38e738064f28e4adea8418990d739ebaf79eecb --- /dev/null +++ b/app/src/main/res/drawable/main_background.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toast_error_bg.xml b/app/src/main/res/drawable/toast_error_bg.xml new file mode 100644 index 0000000000000000000000000000000000000000..da7e4313db252fecbf5c591ef90611da9d2b6941 --- /dev/null +++ b/app/src/main/res/drawable/toast_error_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toast_error_ic.xml b/app/src/main/res/drawable/toast_error_ic.xml new file mode 100644 index 0000000000000000000000000000000000000000..4fd59421e3a4d22e5833246155e6b5bb569a6e83 --- /dev/null +++ b/app/src/main/res/drawable/toast_error_ic.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/drawable/toast_hint_bg.xml b/app/src/main/res/drawable/toast_hint_bg.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e176e56fe879e93cf170014d48dd778410568d0 --- /dev/null +++ b/app/src/main/res/drawable/toast_hint_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toast_info_ic.xml b/app/src/main/res/drawable/toast_info_ic.xml new file mode 100644 index 0000000000000000000000000000000000000000..d8a77f28ea35356037643fef22b0c46e6991839c --- /dev/null +++ b/app/src/main/res/drawable/toast_info_ic.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/toast_success_bg.xml b/app/src/main/res/drawable/toast_success_bg.xml new file mode 100644 index 0000000000000000000000000000000000000000..66603a336c68eccba61356b1e790b1e505a9d4ff --- /dev/null +++ b/app/src/main/res/drawable/toast_success_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toast_success_ic.xml b/app/src/main/res/drawable/toast_success_ic.xml new file mode 100644 index 0000000000000000000000000000000000000000..e66525e54097f79ec894717ca6015e7c9f1fad66 --- /dev/null +++ b/app/src/main/res/drawable/toast_success_ic.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/toast_warn_bg.xml b/app/src/main/res/drawable/toast_warn_bg.xml new file mode 100644 index 0000000000000000000000000000000000000000..df7b0494bdfe792ca0a92fac908ec04506fc4c6d --- /dev/null +++ b/app/src/main/res/drawable/toast_warn_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toast_warn_ic.xml b/app/src/main/res/drawable/toast_warn_ic.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd5389cd758c9c337da535133ab805ea1aaa1f05 --- /dev/null +++ b/app/src/main/res/drawable/toast_warn_ic.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/layout/activity_cas_cloud_debug.xml b/app/src/main/res/layout/activity_cas_cloud_debug.xml deleted file mode 100644 index 90958eb158abeeea2494a2d1e47252da1a16762a..0000000000000000000000000000000000000000 --- a/app/src/main/res/layout/activity_cas_cloud_debug.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - -