Skip to content

Commit 2050bbb

Browse files
authored
fix(Android): Complex initialProperties may fail the app (#186)
1 parent 581863e commit 2050bbb

8 files changed

Lines changed: 134 additions & 25 deletions

File tree

android/app/src/main/java/com/react/testapp/MainActivity.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
//
2+
// Copyright (c) Microsoft Corporation
3+
//
4+
// This source code is licensed under the MIT license found in the
5+
// LICENSE file in the root directory of this source tree.
6+
//
7+
18
package com.react.testapp
29

310
import android.os.Bundle
@@ -32,9 +39,7 @@ class MainActivity : ReactActivity() {
3239
get() = reactNativeHost as TestAppReactNativeHost
3340

3441
private val newComponentActivityIntent = { component: ComponentViewModel ->
35-
ComponentActivity.newIntent(
36-
this, component.name, component.displayName, component.initialProperties
37-
)
42+
ComponentActivity.newIntent(this, component)
3843
}
3944

4045
private val newComponentViewModel = { component: Component ->

android/app/src/main/java/com/react/testapp/component/ComponentActivity.kt

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
//
2+
// Copyright (c) Microsoft Corporation
3+
//
4+
// This source code is licensed under the MIT license found in the
5+
// LICENSE file in the root directory of this source tree.
6+
//
7+
18
package com.react.testapp.component
29

310
import android.app.Activity
@@ -24,22 +31,13 @@ class ComponentActivity : ReactActivity() {
2431
private const val COMPONENT_DISPLAY_NAME = "extra:componentDisplayName"
2532
private const val COMPONENT_INITIAL_PROPERTIES = "extra:componentInitialProperties"
2633

27-
fun newIntent(
28-
activity: Activity,
29-
componentName: String,
30-
componentDisplayName: String,
31-
componentInitialProperties: Map<String, String?>?
32-
): Intent {
34+
fun newIntent(activity: Activity, component: ComponentViewModel): Intent {
3335
return Intent(activity, ComponentActivity::class.java).apply {
34-
putExtra(COMPONENT_NAME, componentName)
35-
putExtra(COMPONENT_DISPLAY_NAME, componentDisplayName)
36-
37-
if (componentInitialProperties != null) {
38-
val bundle = Bundle()
39-
for ((k, v) in componentInitialProperties) {
40-
bundle.putString(k, v)
41-
}
42-
putExtra(COMPONENT_INITIAL_PROPERTIES, bundle)
36+
putExtra(COMPONENT_NAME, component.name)
37+
putExtra(COMPONENT_DISPLAY_NAME, component.displayName)
38+
39+
if (component.initialProperties != null) {
40+
putExtra(COMPONENT_INITIAL_PROPERTIES, component.initialProperties)
4341
}
4442
}
4543
}
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
//
2+
// Copyright (c) Microsoft Corporation
3+
//
4+
// This source code is licensed under the MIT license found in the
5+
// LICENSE file in the root directory of this source tree.
6+
//
7+
18
package com.react.testapp.component
29

10+
import android.os.Bundle
11+
312
data class ComponentViewModel(
413
val name: String,
514
val displayName: String,
6-
val initialProperties: Map<String, String?>?
15+
val initialProperties: Bundle?
716
)

android/app/src/main/java/com/react/testapp/manifest/Manifest.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
//
2+
// Copyright (c) Microsoft Corporation
3+
//
4+
// This source code is licensed under the MIT license found in the
5+
// LICENSE file in the root directory of this source tree.
6+
//
7+
18
package com.react.testapp.manifest
29

10+
import android.os.Bundle
311
import com.squareup.moshi.JsonClass
412

513
@JsonClass(generateAdapter = true)
@@ -13,5 +21,5 @@ data class Manifest(
1321
data class Component(
1422
val appKey: String,
1523
val displayName: String?,
16-
val initialProperties: Map<String, String?>?
24+
val initialProperties: Bundle?
1725
)

android/app/src/main/java/com/react/testapp/manifest/ManifestModule.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
//
2+
// Copyright (c) Microsoft Corporation
3+
//
4+
// This source code is licensed under the MIT license found in the
5+
// LICENSE file in the root directory of this source tree.
6+
//
7+
18
package com.react.testapp.manifest
29

310
import com.squareup.moshi.JsonAdapter
@@ -11,10 +18,13 @@ class ManifestModule {
1118

1219
@Provides
1320
@Singleton
14-
fun providesMoshi(): Moshi = Moshi.Builder().build()
21+
fun providesMoshi(): Moshi {
22+
return Moshi.Builder().add(MoshiBundleAdapter()).build()
23+
}
1524

1625
@Provides
1726
@Singleton
18-
fun providesManifestMoshiAdapter(moshi: Moshi): JsonAdapter<Manifest> =
19-
ManifestJsonAdapter(moshi)
27+
fun providesManifestMoshiAdapter(moshi: Moshi): JsonAdapter<Manifest> {
28+
return ManifestJsonAdapter(moshi)
29+
}
2030
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.react.testapp.manifest
2+
3+
import android.os.Bundle
4+
import com.facebook.react.bridge.Arguments
5+
import com.react.testapp.react.toReadableMap
6+
import com.squareup.moshi.FromJson
7+
import com.squareup.moshi.ToJson
8+
9+
class MoshiBundleAdapter {
10+
11+
@ToJson
12+
@Suppress("unused")
13+
fun toJson(@Suppress("UNUSED_PARAMETER") bundle: Bundle): String {
14+
throw NotImplementedError()
15+
}
16+
17+
@FromJson
18+
@Suppress("unused")
19+
fun fromJson(map: Map<String, Any?>): Bundle? {
20+
return Arguments.toBundle(map.toReadableMap())
21+
}
22+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// Copyright (c) Microsoft Corporation
3+
//
4+
// This source code is licensed under the MIT license found in the
5+
// LICENSE file in the root directory of this source tree.
6+
//
7+
8+
package com.react.testapp.react
9+
10+
import com.facebook.react.bridge.*
11+
12+
fun Map<*, *>.toReadableMap(): ReadableMap {
13+
return Arguments.createMap().also { map ->
14+
for ((k, v) in this) {
15+
map.putValue(k as String, v)
16+
}
17+
}
18+
}
19+
20+
private fun WritableArray.pushValue(value: Any?) {
21+
when (value) {
22+
null -> pushNull()
23+
is Boolean -> pushBoolean(value)
24+
is Double -> pushDouble(value)
25+
is String -> pushString(value)
26+
is ArrayList<*> -> pushArray(toReadableArray(value))
27+
else -> {
28+
pushMap(toReadableMap(value))
29+
}
30+
}
31+
}
32+
33+
private fun WritableMap.putValue(key: String, value: Any?) {
34+
when (value) {
35+
null -> putNull(key)
36+
is Boolean -> putBoolean(key, value)
37+
is Double -> putDouble(key, value)
38+
is String -> putString(key, value)
39+
is ArrayList<*> -> putArray(key, toReadableArray(value))
40+
else -> {
41+
putMap(key, toReadableMap(value))
42+
}
43+
}
44+
}
45+
46+
private fun toReadableArray(list: ArrayList<*>): ReadableArray {
47+
return Arguments.createArray().also { array ->
48+
list.forEach { array.pushValue(it) }
49+
}
50+
}
51+
52+
private fun toReadableMap(obj: Any): ReadableMap {
53+
val map = obj as? Map<*, *> ?: throw NotImplementedError(
54+
"Encountered unknown type while parsing manifest: ${obj::class.qualifiedName}"
55+
)
56+
return map.toReadableMap()
57+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Sun Jan 12 17:37:02 CET 2020
1+
#Mon Aug 10 11:12:44 CEST 2020
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

0 commit comments

Comments
 (0)