Skip to content

Commit f502b0e

Browse files
committed
Feature: Added support for China region.
- Added WeChat Login support. - Added Chinese language support. - Delete account support added. - Added Privacy policy popup on consent screen. - Added popup to display permission purpose. - Excluded firebase crashlytics for China region.
1 parent 74a3977 commit f502b0e

29 files changed

+2087
-115
lines changed

app/build.gradle

+41-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ plugins {
22
id 'com.android.application'
33
id 'com.google.protobuf'
44
id 'com.google.gms.google-services'
5-
id 'com.google.firebase.crashlytics'
65
id 'kotlin-android'
76
id 'org.jetbrains.kotlin.android'
87
id "dagger.hilt.android.plugin"
@@ -45,9 +44,24 @@ def defaultTermsOfUseUrl = "https://rainmaker.espressif.com/docs/terms-of-use.ht
4544
def defaultUserPool = "2"
4645
def matterBuild = false
4746

47+
def defaultChinaBaseUrl = "https://api2.rainmaker.espressif.com.cn"
48+
def defaultChinaAuthUrl = "https://api2.rainmaker.espressif.com.cn"
49+
def defaultChinaClientId = "6m3FgmvJSt4g6pDrHgfpYj"
50+
def defaultChinaClaimBaseUrl = "https://claiming.rainmaker.espressif.com.cn"
51+
def defaultChinaPrivacyUrl = "https://rainmaker.espressif.com/zh-hans/docs/privacy-policy-cn/"
52+
def defaultChinaTermsOfUseUrl = "https://rainmaker.espressif.com/zh-hans/docs/terms-of-use-cn/"
53+
54+
// Please configure WeChat App id to support WeChat login for China region
55+
def weChatIdForLogin = "your_we_chat_id"
56+
4857
def localProperties = new Properties()
4958
localProperties.load(new FileInputStream(rootProject.file("local.properties")))
5059

60+
// Conditional plugin
61+
if (localProperties.getProperty("isChinaRegion", "false") != "true") {
62+
apply plugin: 'com.google.firebase.crashlytics'
63+
}
64+
5165
android {
5266

5367
compileSdk 34
@@ -56,8 +70,8 @@ android {
5670
applicationId "com.espressif.rainmaker"
5771
minSdkVersion 27
5872
targetSdkVersion 34
59-
versionCode 130
60-
versionName "3.4.2 - ${getGitHash()}"
73+
versionCode 132
74+
versionName "3.5.0 - ${getGitHash()}"
6175
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
6276

6377
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
@@ -129,6 +143,19 @@ android {
129143
buildConfigField "String", "TOKEN_URL", '"' + authUrl + "/token" + '"'
130144
buildConfigField "String", "REDIRECT_URI", '"' + redirectUri + '"'
131145

146+
def chinaClientId = localProperties.getProperty("chinaClientId", defaultChinaClientId)
147+
def chinaAuthUrl = localProperties.getProperty("chinaAuthUrl", defaultChinaAuthUrl)
148+
149+
buildConfigField "boolean", "isChinaRegion", localProperties.getProperty("isChinaRegion", "false")
150+
buildConfigField "String", "CHINA_WE_CHAT_APP_ID", '"' + localProperties.getProperty("weChatId", weChatIdForLogin) + '"'
151+
buildConfigField "String", "CHINA_BASE_URL", '"' + localProperties.getProperty("chinaBaseUrl", defaultChinaBaseUrl) + '"'
152+
buildConfigField "String", "CHINA_AUTH_URL", '"' + chinaAuthUrl + '"'
153+
buildConfigField "String", "CHINA_TOKEN_URL", '"' + chinaAuthUrl + "/token" + '"'
154+
buildConfigField "String", "CHINA_CLIENT_ID", '"' + chinaClientId + '"'
155+
buildConfigField "String", "CHINA_CLAIM_BASE_URL", '"' + localProperties.getProperty("chinaClaimBaseUrl", defaultChinaClaimBaseUrl) + '"'
156+
buildConfigField "String", "CHINA_PRIVACY_URL", '"' + localProperties.getProperty("chinaPrivacyUrl", defaultChinaPrivacyUrl) + '"'
157+
buildConfigField "String", "CHINA_TERMS_URL", '"' + localProperties.getProperty("chinaTermsOfUseUrl", defaultChinaTermsOfUseUrl) + '"'
158+
132159
def gitHubUrl = authUrl + "/authorize?identity_provider=" + gitHubIdentityProvider +
133160
"&redirect_uri=" + redirectUri + "&response_type=CODE&client_id=" + clientId
134161
def googleUrl = authUrl + "/authorize?identity_provider=" + googleIdentityProvider +
@@ -189,6 +216,10 @@ android {
189216
}
190217
}
191218

219+
lintOptions {
220+
disable 'UnspecifiedImmutableFlag'
221+
}
222+
192223
namespace 'com.espressif.rainmaker'
193224
}
194225

@@ -241,10 +272,13 @@ dependencies {
241272
// Firebase
242273
implementation platform(libs.firebase.bom)
243274
implementation libs.firebase.messaging
244-
implementation libs.firebase.analytics
245-
implementation libs.firebase.crashlytics
246275
implementation libs.play.services.gcm
247276

277+
if (localProperties.getProperty("isChinaRegion", "false") != "true") {
278+
implementation libs.firebase.analytics
279+
implementation libs.firebase.crashlytics
280+
}
281+
248282
// Connected Home
249283
implementation libs.play.services.base
250284
implementation libs.play.services.home
@@ -267,6 +301,8 @@ dependencies {
267301
implementation libs.bcpkix.jdk15to18
268302
implementation libs.bcprov.jdk15to18
269303

304+
implementation libs.wechat.sdk.android.without.mta
305+
270306
testImplementation libs.junit
271307
androidTestImplementation libs.runner
272308
androidTestImplementation libs.espresso.core

app/src/main/AndroidManifest.xml

+29-4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,22 @@
6464

6565
</activity>
6666

67+
<activity
68+
android:name=".wxapi.WXEntryActivity"
69+
android:exported="true"
70+
android:label="@string/app_name"
71+
android:launchMode="singleTask"
72+
android:taskAffinity="com.espressif.rainmaker">
73+
<intent-filter>
74+
<action android:name="android.intent.action.VIEW" />
75+
76+
<category android:name="android.intent.category.DEFAULT" />
77+
<category android:name="android.intent.category.BROWSABLE" />
78+
79+
<data android:scheme="wxcced7aa3898dff73" /> <!-- Replace with your AppID -->
80+
</intent-filter>
81+
</activity>
82+
6783
<activity
6884
android:name="com.espressif.ui.activities.MainActivity"
6985
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
@@ -349,10 +365,19 @@
349365
android:name="com.google.ar.core"
350366
android:value="optional" />
351367

368+
<receiver
369+
android:name="com.espressif.AppRegister"
370+
android:exported="true"
371+
android:permission="com.tencent.mm.plugin.permission.SEND">
372+
<intent-filter>
373+
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" />
374+
</intent-filter>
375+
</receiver>
376+
352377
</application>
353378

354-
<!-- <queries>-->
355-
<!-- <package android:name="com.google.ar.core" />-->
356-
<!-- </queries>-->
379+
<queries>
380+
<package android:name="com.tencent.mm" />
381+
</queries>
357382

358-
</manifest>
383+
</manifest>

app/src/main/java/com/espressif/AppConstants.kt

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
package com.espressif
1616

17-
import com.espressif.rainmaker.BuildConfig
18-
1917
class AppConstants {
2018

2119
companion object {
@@ -221,8 +219,8 @@ class AppConstants {
221219
const val URL_USER_NODE_STATUS = "/user/nodes/status"
222220
const val URL_USER_NODES_PARAMS = "/user/nodes/params"
223221

224-
const val URL_CLAIM_INITIATE = BuildConfig.CLAIM_BASE_URL + "/claim/initiate"
225-
const val URL_CLAIM_VERIFY = BuildConfig.CLAIM_BASE_URL + "/claim/verify"
222+
const val URL_CLAIM_INITIATE = "/claim/initiate"
223+
const val URL_CLAIM_VERIFY = "/claim/verify"
226224
const val URL_USER_NODE_GROUP = "/user/node_group"
227225
const val URL_USER_NODES_SHARING_REQUESTS = "/user/nodes/sharing/requests"
228226
const val URL_USER_NODES_SHARING = "/user/nodes/sharing"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.espressif;
2+
3+
import android.content.BroadcastReceiver;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
7+
import com.espressif.rainmaker.BuildConfig;
8+
import com.tencent.mm.opensdk.openapi.IWXAPI;
9+
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
10+
11+
public class AppRegister extends BroadcastReceiver {
12+
13+
@Override
14+
public void onReceive(Context context, Intent intent) {
15+
final IWXAPI api = WXAPIFactory.createWXAPI(context, null, false);
16+
17+
// Register the app to WeChat
18+
api.registerApp(BuildConfig.CHINA_WE_CHAT_APP_ID);
19+
}
20+
}

app/src/main/java/com/espressif/EspApplication.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public class EspApplication extends Application {
127127
private KeyStore keyStore = null;
128128

129129
public String mGroupId, mFabricId, mRootCa, mIpk, groupCatIdOperate;
130+
public static boolean loggedInUsingWeChat = false;
130131

131132
public enum AppState {
132133
NO_USER_LOGIN,
@@ -161,9 +162,13 @@ public void onCreate() {
161162
mdnsManager = mDNSManager.getInstance(getApplicationContext(), AppConstants.MDNS_SERVICE_TYPE, listener);
162163
}
163164

164-
if (Utils.isPlayServicesAvailable(getApplicationContext())) {
165-
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
166-
setupNotificationChannels();
165+
if (BuildConfig.isChinaRegion) {
166+
BASE_URL = BuildConfig.CHINA_BASE_URL;
167+
} else {
168+
if (Utils.isPlayServicesAvailable(getApplicationContext())) {
169+
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
170+
setupNotificationChannels();
171+
}
167172
}
168173
}
169174

@@ -1008,6 +1013,7 @@ private void clearData() {
10081013
localDeviceMap.clear();
10091014
groupMap.clear();
10101015
automations.clear();
1016+
loggedInUsingWeChat = false;
10111017
}
10121018

10131019
public void startLocalDeviceDiscovery() {

app/src/main/java/com/espressif/cloudapi/ApiInterface.java

+9
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ Call<ResponseBody> oauthLogin(@Url String url, @Header("Content-type") String co
7474
@Field("code") String code,
7575
@Field("redirect_uri") String redirect_uri);
7676

77+
@FormUrlEncoded
78+
@POST
79+
Call<ResponseBody> oauthLoginForWeChat(@Url String url, @Header("Content-type") String contentType,
80+
@Field("grant_type") String grant_type,
81+
@Field("client_id") String client_id,
82+
@Field("code") String code,
83+
@Field("wechat_token_only") boolean weChatTokenOnly,
84+
@Field("redirect_uri") String redirect_uri);
85+
7786
// Get Supported Versions
7887
@GET
7988
Call<ResponseBody> getSupportedVersions(@Url String url);

app/src/main/java/com/espressif/cloudapi/ApiManager.java

+78-4
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public void onFailure(Call<ResponseBody> call, Throwable t) {
238238
public void getOAuthToken(String code, final ApiResponseListener listener) {
239239

240240
Log.d(TAG, "Get OAuth Token");
241-
String url = BuildConfig.TOKEN_URL;
241+
String url = getTokenUrl();
242242

243243
try {
244244
apiInterface.oauthLogin(url, "application/x-www-form-urlencoded",
@@ -294,10 +294,68 @@ public void onFailure(Call<ResponseBody> call, Throwable t) {
294294
}
295295
}
296296

297+
public void getOAuthTokenForWechat(String code, final ApiResponseListener listener) {
298+
299+
Log.d(TAG, "Get OAuth Token for WeChat");
300+
String url = getTokenUrl();
301+
302+
try {
303+
apiInterface.oauthLoginForWeChat(url, "application/x-www-form-urlencoded",
304+
"authorization_code", BuildConfig.CHINA_CLIENT_ID, code, true,
305+
BuildConfig.REDIRECT_URI).enqueue(new Callback<ResponseBody>() {
306+
@Override
307+
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
308+
309+
Log.d(TAG, "Get OAuth Token for WeChat, Response code : " + response.code());
310+
try {
311+
if (response.isSuccessful()) {
312+
313+
String jsonResponse = response.body().string();
314+
JSONObject jsonObject = new JSONObject(jsonResponse);
315+
idToken = jsonObject.getString(AppConstants.KEY_ID_TOKEN);
316+
accessToken = jsonObject.getString(AppConstants.KEY_ACCESS_TOKEN);
317+
refreshToken = jsonObject.getString(AppConstants.KEY_REFRESH_TOKEN);
318+
isOAuthLogin = true;
319+
320+
SharedPreferences.Editor editor = sharedPreferences.edit();
321+
editor.putString(AppConstants.KEY_ID_TOKEN, idToken);
322+
editor.putString(AppConstants.KEY_ACCESS_TOKEN, accessToken);
323+
editor.putString(AppConstants.KEY_REFRESH_TOKEN, refreshToken);
324+
editor.putBoolean(AppConstants.KEY_IS_OAUTH_LOGIN, true);
325+
editor.apply();
326+
327+
getTokenAndUserId();
328+
listener.onSuccess(null);
329+
330+
} else {
331+
String jsonErrResponse = response.errorBody().string();
332+
processError(jsonErrResponse, listener, "Failed to get WeChat login token.");
333+
}
334+
} catch (IOException e) {
335+
e.printStackTrace();
336+
listener.onResponseFailure(e);
337+
} catch (JSONException e) {
338+
e.printStackTrace();
339+
listener.onResponseFailure(e);
340+
}
341+
}
342+
343+
@Override
344+
public void onFailure(Call<ResponseBody> call, Throwable t) {
345+
t.printStackTrace();
346+
listener.onNetworkFailure(new Exception(t));
347+
}
348+
});
349+
} catch (Exception e) {
350+
e.printStackTrace();
351+
listener.onNetworkFailure(e);
352+
}
353+
}
354+
297355
public void getOAuthTokenForController(String code, final ApiResponseListener listener) {
298356

299357
Log.d(TAG, "Get OAuth Token for Matter Controller");
300-
String url = BuildConfig.TOKEN_URL;
358+
String url = getTokenUrl();
301359

302360
try {
303361
apiInterface.oauthLogin(url, "application/x-www-form-urlencoded",
@@ -2679,8 +2737,9 @@ public void run() {
26792737
public void initiateClaim(JsonObject body, final ApiResponseListener listener) {
26802738

26812739
Log.d(TAG, "Initiate Claiming...");
2740+
String url = getClaimBaseUrl() + AppConstants.URL_CLAIM_INITIATE;
26822741

2683-
apiInterface.initiateClaiming(AppConstants.URL_CLAIM_INITIATE, accessToken, body).enqueue(new Callback<ResponseBody>() {
2742+
apiInterface.initiateClaiming(url, accessToken, body).enqueue(new Callback<ResponseBody>() {
26842743

26852744
@Override
26862745
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
@@ -2716,8 +2775,9 @@ public void onFailure(Call<ResponseBody> call, Throwable t) {
27162775
public void verifyClaiming(JsonObject body, final ApiResponseListener listener) {
27172776

27182777
Log.d(TAG, "Verifying Claiming...");
2778+
String url = getClaimBaseUrl() + AppConstants.URL_CLAIM_VERIFY;
27192779

2720-
apiInterface.verifyClaiming(AppConstants.URL_CLAIM_VERIFY, accessToken, body).enqueue(new Callback<ResponseBody>() {
2780+
apiInterface.verifyClaiming(url, accessToken, body).enqueue(new Callback<ResponseBody>() {
27212781

27222782
@Override
27232783
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
@@ -4761,6 +4821,20 @@ private String getBaseUrl() {
47614821
return EspApplication.BASE_URL + AppConstants.PATH_SEPARATOR + AppConstants.CURRENT_VERSION;
47624822
}
47634823

4824+
private String getTokenUrl() {
4825+
if (BuildConfig.isChinaRegion) {
4826+
return BuildConfig.CHINA_TOKEN_URL;
4827+
}
4828+
return BuildConfig.TOKEN_URL;
4829+
}
4830+
4831+
private String getClaimBaseUrl() {
4832+
if (BuildConfig.isChinaRegion) {
4833+
return BuildConfig.CHINA_CLAIM_BASE_URL;
4834+
}
4835+
return BuildConfig.CLAIM_BASE_URL;
4836+
}
4837+
47644838
private String getLoginEndpointUrl() {
47654839
String endpoint = Integer.valueOf(BuildConfig.USER_POOL) == AppConstants.USER_POOL_1 ? AppConstants.URL_LOGIN : AppConstants.URL_LOGIN_2;
47664840
String loginUrl = getBaseUrl() + endpoint;

0 commit comments

Comments
 (0)