diff --git a/android/.gradle/3.3/taskArtifacts/fileHashes.bin b/android/.gradle/3.3/taskArtifacts/fileHashes.bin
new file mode 100644
index 0000000..3322578
Binary files /dev/null and b/android/.gradle/3.3/taskArtifacts/fileHashes.bin differ
diff --git a/android/.gradle/3.3/taskArtifacts/fileSnapshots.bin b/android/.gradle/3.3/taskArtifacts/fileSnapshots.bin
new file mode 100644
index 0000000..1eb37ee
Binary files /dev/null and b/android/.gradle/3.3/taskArtifacts/fileSnapshots.bin differ
diff --git a/android/.gradle/3.3/taskArtifacts/taskArtifacts.bin b/android/.gradle/3.3/taskArtifacts/taskArtifacts.bin
new file mode 100644
index 0000000..841cc3c
Binary files /dev/null and b/android/.gradle/3.3/taskArtifacts/taskArtifacts.bin differ
diff --git a/android/.gradle/3.3/taskArtifacts/taskArtifacts.lock b/android/.gradle/3.3/taskArtifacts/taskArtifacts.lock
new file mode 100644
index 0000000..6374f45
Binary files /dev/null and b/android/.gradle/3.3/taskArtifacts/taskArtifacts.lock differ
diff --git a/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin
new file mode 100644
index 0000000..3e90666
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin differ
diff --git a/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock
new file mode 100644
index 0000000..6949929
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock differ
diff --git a/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin
new file mode 100644
index 0000000..5a9e061
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin differ
diff --git a/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock
new file mode 100644
index 0000000..afc8406
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock differ
diff --git a/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin
new file mode 100644
index 0000000..2731a94
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin differ
diff --git a/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock
new file mode 100644
index 0000000..a911342
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock differ
diff --git a/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin
new file mode 100644
index 0000000..0f9c595
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin differ
diff --git a/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock
new file mode 100644
index 0000000..378ee42
Binary files /dev/null and b/android/.gradle/3.3/tasks/_app_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin
new file mode 100644
index 0000000..7198e7a
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock
new file mode 100644
index 0000000..2bb339c
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin
new file mode 100644
index 0000000..0fa7ec9
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock
new file mode 100644
index 0000000..34c115a
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin
new file mode 100644
index 0000000..7198e7a
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock
new file mode 100644
index 0000000..092d459
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin
new file mode 100644
index 0000000..0fa7ec9
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin differ
diff --git a/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock
new file mode 100644
index 0000000..1e30575
Binary files /dev/null and b/android/.gradle/3.3/tasks/_mylibrary_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock differ
diff --git a/android/.idea/.name b/android/.idea/.name
new file mode 100644
index 0000000..f7cc9d7
--- /dev/null
+++ b/android/.idea/.name
@@ -0,0 +1 @@
+updataDemo
\ No newline at end of file
diff --git a/android/.idea/compiler.xml b/android/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/android/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/copyright/profiles_settings.xml b/android/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..e7bedf3
--- /dev/null
+++ b/android/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/android/.idea/gradle.xml b/android/.idea/gradle.xml
new file mode 100644
index 0000000..08d2b7a
--- /dev/null
+++ b/android/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/android_jsc_r174650.xml b/android/.idea/libraries/android_jsc_r174650.xml
new file mode 100644
index 0000000..6b46cda
--- /dev/null
+++ b/android/.idea/libraries/android_jsc_r174650.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/appcompat_v7_23_0_1.xml b/android/.idea/libraries/appcompat_v7_23_0_1.xml
new file mode 100644
index 0000000..0f4c970
--- /dev/null
+++ b/android/.idea/libraries/appcompat_v7_23_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/bolts_tasks_1_4_0.xml b/android/.idea/libraries/bolts_tasks_1_4_0.xml
new file mode 100644
index 0000000..3f0dbce
--- /dev/null
+++ b/android/.idea/libraries/bolts_tasks_1_4_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/drawee_1_0_1.xml b/android/.idea/libraries/drawee_1_0_1.xml
new file mode 100644
index 0000000..d268471
--- /dev/null
+++ b/android/.idea/libraries/drawee_1_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/fastjson_1_2_37.xml b/android/.idea/libraries/fastjson_1_2_37.xml
new file mode 100644
index 0000000..6605696
--- /dev/null
+++ b/android/.idea/libraries/fastjson_1_2_37.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/fbcore_1_0_1.xml b/android/.idea/libraries/fbcore_1_0_1.xml
new file mode 100644
index 0000000..3744a78
--- /dev/null
+++ b/android/.idea/libraries/fbcore_1_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/fresco_1_0_1.xml b/android/.idea/libraries/fresco_1_0_1.xml
new file mode 100644
index 0000000..611b1ff
--- /dev/null
+++ b/android/.idea/libraries/fresco_1_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/imagepipeline_1_0_1.xml b/android/.idea/libraries/imagepipeline_1_0_1.xml
new file mode 100644
index 0000000..75a34c8
--- /dev/null
+++ b/android/.idea/libraries/imagepipeline_1_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/imagepipeline_base_1_0_1.xml b/android/.idea/libraries/imagepipeline_base_1_0_1.xml
new file mode 100644
index 0000000..e981b8a
--- /dev/null
+++ b/android/.idea/libraries/imagepipeline_base_1_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/imagepipeline_okhttp3_1_0_1.xml b/android/.idea/libraries/imagepipeline_okhttp3_1_0_1.xml
new file mode 100644
index 0000000..f189601
--- /dev/null
+++ b/android/.idea/libraries/imagepipeline_okhttp3_1_0_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/javax_inject_1.xml b/android/.idea/libraries/javax_inject_1.xml
new file mode 100644
index 0000000..eebeedd
--- /dev/null
+++ b/android/.idea/libraries/javax_inject_1.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/jsr305_3_0_0.xml b/android/.idea/libraries/jsr305_3_0_0.xml
new file mode 100644
index 0000000..b9fbaab
--- /dev/null
+++ b/android/.idea/libraries/jsr305_3_0_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/library_1_6_3.xml b/android/.idea/libraries/library_1_6_3.xml
new file mode 100644
index 0000000..a764ef5
--- /dev/null
+++ b/android/.idea/libraries/library_1_6_3.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/okhttp_3_6_0.xml b/android/.idea/libraries/okhttp_3_6_0.xml
new file mode 100644
index 0000000..472aed6
--- /dev/null
+++ b/android/.idea/libraries/okhttp_3_6_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/okhttp_urlconnection_3_6_0.xml b/android/.idea/libraries/okhttp_urlconnection_3_6_0.xml
new file mode 100644
index 0000000..a34993b
--- /dev/null
+++ b/android/.idea/libraries/okhttp_urlconnection_3_6_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/okio_1_13_0.xml b/android/.idea/libraries/okio_1_13_0.xml
new file mode 100644
index 0000000..a855abb
--- /dev/null
+++ b/android/.idea/libraries/okio_1_13_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/react_native_0_47_1.xml b/android/.idea/libraries/react_native_0_47_1.xml
new file mode 100644
index 0000000..667f2d3
--- /dev/null
+++ b/android/.idea/libraries/react_native_0_47_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/soloader_0_1_0.xml b/android/.idea/libraries/soloader_0_1_0.xml
new file mode 100644
index 0000000..114fadb
--- /dev/null
+++ b/android/.idea/libraries/soloader_0_1_0.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/staticlayout_proxy_1_0.xml b/android/.idea/libraries/staticlayout_proxy_1_0.xml
new file mode 100644
index 0000000..547ad80
--- /dev/null
+++ b/android/.idea/libraries/staticlayout_proxy_1_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/support_annotations_23_0_1.xml b/android/.idea/libraries/support_annotations_23_0_1.xml
new file mode 100644
index 0000000..f11118e
--- /dev/null
+++ b/android/.idea/libraries/support_annotations_23_0_1.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/support_v4_23_0_1.xml b/android/.idea/libraries/support_v4_23_0_1.xml
new file mode 100644
index 0000000..aef7719
--- /dev/null
+++ b/android/.idea/libraries/support_v4_23_0_1.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/libraries/textlayoutbuilder_1_0_0.xml b/android/.idea/libraries/textlayoutbuilder_1_0_0.xml
new file mode 100644
index 0000000..5e29fdc
--- /dev/null
+++ b/android/.idea/libraries/textlayoutbuilder_1_0_0.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml
new file mode 100644
index 0000000..3f43bef
--- /dev/null
+++ b/android/.idea/misc.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/modules.xml b/android/.idea/modules.xml
new file mode 100644
index 0000000..4ba415f
--- /dev/null
+++ b/android/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/runConfigurations.xml b/android/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/android/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.idea/workspace.xml b/android/.idea/workspace.xml
new file mode 100644
index 0000000..b593480
--- /dev/null
+++ b/android/.idea/workspace.xml
@@ -0,0 +1,3603 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1502864846742
+
+
+ 1502864846742
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/BUCK b/android/app/BUCK
new file mode 100644
index 0000000..63aa929
--- /dev/null
+++ b/android/app/BUCK
@@ -0,0 +1,65 @@
+# To learn about Buck see [Docs](https://buckbuild.com/).
+# To run your application with Buck:
+# - install Buck
+# - `npm start` - to start the packager
+# - `cd android`
+# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
+# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
+# - `buck install -r android/app` - compile, install and run application
+#
+
+lib_deps = []
+
+for jarfile in glob(['libs/*.jar']):
+ name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
+ lib_deps.append(':' + name)
+ prebuilt_jar(
+ name = name,
+ binary_jar = jarfile,
+ )
+
+for aarfile in glob(['libs/*.aar']):
+ name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
+ lib_deps.append(':' + name)
+ android_prebuilt_aar(
+ name = name,
+ aar = aarfile,
+ )
+
+android_library(
+ name = "all-libs",
+ exported_deps = lib_deps,
+)
+
+android_library(
+ name = "app-code",
+ srcs = glob([
+ "src/main/java/**/*.java",
+ ]),
+ deps = [
+ ":all-libs",
+ ":build_config",
+ ":res",
+ ],
+)
+
+android_build_config(
+ name = "build_config",
+ package = "com.updatademo",
+)
+
+android_resource(
+ name = "res",
+ package = "com.updatademo",
+ res = "src/main/res",
+)
+
+android_binary(
+ name = "app",
+ keystore = "//android/keystores:debug",
+ manifest = "src/main/AndroidManifest.xml",
+ package_type = "debug",
+ deps = [
+ ":app-code",
+ ],
+)
diff --git a/android/app/app.iml b/android/app/app.iml
new file mode 100644
index 0000000..7df8f75
--- /dev/null
+++ b/android/app/app.iml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 0000000..40d9863
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,157 @@
+apply plugin: "com.android.application"
+/**
+ * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
+ * and bundleReleaseJsAndAssets).
+ * These basically call `react-native bundle` with the correct arguments during the Android build
+ * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
+ * bundle directly from the development server. Below you can see all the possible configurations
+ * and their defaults. If you decide to add a configuration block, make sure to add it before the
+ * `apply from: "../../node_modules/react-native/react.gradle"` line.
+ *
+ * project.ext.react = [
+ * // the name of the generated asset file containing your JS bundle
+ * bundleAssetName: "index.android.bundle",
+ *
+ * // the entry file for bundle generation
+ * entryFile: "index.android.js",
+ *
+ * // whether to bundle JS and assets in debug mode
+ * bundleInDebug: false,
+ *
+ * // whether to bundle JS and assets in release mode
+ * bundleInRelease: true,
+ *
+ * // whether to bundle JS and assets in another build variant (if configured).
+ * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
+ * // The configuration property can be in the following formats
+ * // 'bundleIn${productFlavor}${buildType}'
+ * // 'bundleIn${buildType}'
+ * // bundleInFreeDebug: true,
+ * // bundleInPaidRelease: true,
+ * // bundleInBeta: true,
+ *
+ * // whether to disable dev mode in custom build variants (by default only disabled in release)
+ * // for example: to disable dev mode in the staging build type (if configured)
+ * devDisabledInStaging: true,
+ * // The configuration property can be in the following formats
+ * // 'devDisabledIn${productFlavor}${buildType}'
+ * // 'devDisabledIn${buildType}'
+ *
+ * // the root of your project, i.e. where "package.json" lives
+ * root: "../../",
+ *
+ * // where to put the JS bundle asset in debug mode
+ * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
+ *
+ * // where to put the JS bundle asset in release mode
+ * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in debug mode
+ * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in release mode
+ * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
+ *
+ * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
+ * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
+ * // date; if you have any other folders that you want to ignore for performance reasons (gradle
+ * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
+ * // for example, you might want to remove it from here.
+ * inputExcludes: ["android/**", "ios/**"],
+ *
+ * // override which node gets called and with what additional arguments
+ * nodeExecutableAndArgs: ["node"],
+ *
+ * // supply additional arguments to the packager
+ * extraPackagerArgs: []
+ * ]
+ */
+
+apply from: "../../node_modules/react-native/react.gradle"
+
+/**
+ * Set this to true to create two separate APKs instead of one:
+ * - An APK that only works on ARM devices
+ * - An APK that only works on x86 devices
+ * The advantage is the size of the APK is reduced by about 4MB.
+ * Upload all the APKs to the Play Store and people will download
+ * the correct one based on the CPU architecture of their device.
+ */
+def enableSeparateBuildPerCPUArchitecture = false
+
+/**
+ * Run Proguard to shrink the Java bytecode in release builds.
+ */
+def enableProguardInReleaseBuilds = false
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion '25.0.0'
+
+ defaultConfig {
+ applicationId "com.updatademo"
+ minSdkVersion 16
+ targetSdkVersion 21
+ versionCode 1
+ versionName "1.0"
+ ndk {
+ abiFilters "armeabi-v7a", "x86"
+ }
+ }
+ splits {
+ abi {
+ reset()
+ enable enableSeparateBuildPerCPUArchitecture
+ universalApk false // If true, also generate a universal APK
+ include "armeabi-v7a", "x86"
+ }
+ }
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs'] // 若不想编译jni代码,可直接引用so库,ndk编译相关脚本注释掉
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled enableProguardInReleaseBuilds
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ }
+ }
+ // applicationVariants are e.g. debug, release
+// applicationVariants.all { variant ->
+// variant.outputs.each { output ->
+// // For each separate APK per architecture, set a unique version code as described here:
+// // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
+// def versionCodes = ["armeabi-v7a":1, "x86":2]
+// def abi = output.getFilter(OutputFile.ABI)
+// if (abi != null) { // null for the universal-debug, universal-release variants
+// output.versionCodeOverride =
+// versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
+// }
+// }
+// }
+
+ lintOptions {
+ abortOnError false
+ }
+
+
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ compile 'com.android.support:appcompat-v7:23.0.1'
+ compile 'com.facebook.react:react-native:+'
+ compile project(':mylibrary')
+}
+
+// Run this once to be able to run the application with BUCK
+// puts all compile dependencies into folder libs for BUCK to use
+task copyDownloadableDepsToLibs(type: Copy) {
+ from configurations.compile
+ into 'libs'
+}
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
new file mode 100644
index 0000000..6e8516c
--- /dev/null
+++ b/android/app/proguard-rules.pro
@@ -0,0 +1,70 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Disabling obfuscation is useful if you collect stack traces from production crashes
+# (unless you are using a system that supports de-obfuscate the stack traces).
+-dontobfuscate
+
+# React Native
+
+# Keep our interfaces so they can be used by other ProGuard rules.
+# See http://sourceforge.net/p/proguard/bugs/466/
+-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
+-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
+-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
+
+# Do not strip any method/class that is annotated with @DoNotStrip
+-keep @com.facebook.proguard.annotations.DoNotStrip class *
+-keep @com.facebook.common.internal.DoNotStrip class *
+-keepclassmembers class * {
+ @com.facebook.proguard.annotations.DoNotStrip *;
+ @com.facebook.common.internal.DoNotStrip *;
+}
+
+-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
+ void set*(***);
+ *** get*();
+}
+
+-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
+-keep class * extends com.facebook.react.bridge.NativeModule { *; }
+-keepclassmembers,includedescriptorclasses class * { native ; }
+-keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
+-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; }
+-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
+
+-dontwarn com.facebook.react.**
+
+# TextLayoutBuilder uses a non-public Android constructor within StaticLayout.
+# See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details.
+-dontwarn android.text.StaticLayout
+
+# okhttp
+
+-keepattributes Signature
+-keepattributes *Annotation*
+-keep class okhttp3.** { *; }
+-keep interface okhttp3.** { *; }
+-dontwarn okhttp3.**
+
+# okio
+
+-keep class sun.misc.Unsafe { *; }
+-dontwarn java.nio.file.*
+-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
+-dontwarn okio.**
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5855b19
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/assets/updataDemo.zip b/android/app/src/main/assets/updataDemo.zip
new file mode 100644
index 0000000..8f283bf
Binary files /dev/null and b/android/app/src/main/assets/updataDemo.zip differ
diff --git a/android/app/src/main/java/com/updatademo/MyApplication.java b/android/app/src/main/java/com/updatademo/MyApplication.java
new file mode 100644
index 0000000..5dc8d1e
--- /dev/null
+++ b/android/app/src/main/java/com/updatademo/MyApplication.java
@@ -0,0 +1,18 @@
+package com.updatademo;
+
+import android.app.Application;
+
+import com.liulishuo.filedownloader.FileDownloader;
+
+/**
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class MyApplication extends Application {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ FileDownloader.setupOnApplicationOnCreate(this);
+ }
+}
diff --git a/android/app/src/main/java/com/updatademo/MyReactActivity.java b/android/app/src/main/java/com/updatademo/MyReactActivity.java
new file mode 100644
index 0000000..efce687
--- /dev/null
+++ b/android/app/src/main/java/com/updatademo/MyReactActivity.java
@@ -0,0 +1,130 @@
+package com.updatademo;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.KeyEvent;
+
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.ReactRootView;
+import com.facebook.react.common.LifecycleState;
+import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
+import com.facebook.react.shell.MainReactPackage;
+
+/**
+ * Created by Lynn on 2017/8/16.
+ */
+
+public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
+ private static final int OVERLAY_PERMISSION_REQ_CODE = 1000;
+ private ReactRootView mReactRootView;
+ private ReactInstanceManager mReactInstanceManager;
+
+
+
+ private String jsBundlePath="";
+ private String moduleName="";
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.jsBundlePath=getIntent().getExtras().getString("jsbundlePath");
+ this.moduleName=getIntent().getExtras().getString("moduleName");
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (!Settings.canDrawOverlays(this)) {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+ Uri.parse("package:" + getPackageName()));
+ startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
+ }
+ }
+
+
+ mReactRootView = new ReactRootView(this);
+ mReactInstanceManager = ReactInstanceManager.builder()
+ .setApplication(getApplication())
+// .setBundleAssetName("index.android.bundle")
+// .setJSMainModuleName("index.android")
+ .setJSBundleFile(this.jsBundlePath)
+ .addPackage(new MainReactPackage())
+ .setUseDeveloperSupport(false)
+ .setInitialLifecycleState(LifecycleState.RESUMED)
+ .build();
+
+ // 注意这里的MyReactNativeApp必须对应“index.android.js”中的
+ // “AppRegistry.registerComponent()”的第一个参数
+ mReactRootView.startReactApplication(mReactInstanceManager, this.moduleName, null);
+
+ setContentView(mReactRootView);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (!Settings.canDrawOverlays(this)) {
+
+ }
+ }
+ }
+ }
+
+
+ @Override
+ public void invokeDefaultOnBackPressed() {
+ super.onBackPressed();
+ }
+
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ if (mReactInstanceManager != null) {
+ mReactInstanceManager.onHostPause(this);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (mReactInstanceManager != null) {
+ mReactInstanceManager.onHostResume(this, this);
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (mReactInstanceManager != null) {
+ mReactInstanceManager.onHostDestroy();
+ }
+ }
+
+
+ @Override
+ public void onBackPressed() {
+ if (mReactInstanceManager != null) {
+ mReactInstanceManager.onBackPressed();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
+ mReactInstanceManager.showDevOptionsDialog();
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+
+}
diff --git a/android/app/src/main/java/com/updatademo/StartPage.java b/android/app/src/main/java/com/updatademo/StartPage.java
new file mode 100644
index 0000000..f6adfdd
--- /dev/null
+++ b/android/app/src/main/java/com/updatademo/StartPage.java
@@ -0,0 +1,65 @@
+package com.updatademo;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.View;
+import android.widget.Button;
+
+import com.yyh.lib.bsdiff.downloader.ModuleManager;
+import com.yyh.lib.bsdiff.downloader.RnModuleDiffUpdateService;
+
+
+/**
+ * Created by Lynn on 2017/8/16.
+ */
+
+public class StartPage extends Activity implements View.OnClickListener {
+
+
+ private Button action_bt0;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.startpage_layout);
+ initView();
+ Intent intent = new Intent(this, RnModuleDiffUpdateService.class);
+ startService(intent);
+ }
+
+
+ private void initView() {
+ action_bt0 = (Button) findViewById(R.id.action_bt0);
+ action_bt0.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.action_bt0:
+ action();
+ break;
+ }
+ }
+
+
+ private void action() {
+ String moduleName = "updataDemo";
+ String path = ModuleManager.getMoudleJsBundleFile(this, moduleName);
+ Intent intent = new Intent(this, MyReactActivity.class);
+ intent.putExtra("jsbundlePath", path);
+ intent.putExtra("moduleName", moduleName);
+ startActivity(intent);
+ }
+
+
+
+ @Override
+ public void onBackPressed() {
+ Intent intent = new Intent(this, RnModuleDiffUpdateService.class);
+ stopService(intent);
+ super.onBackPressed();
+ }
+}
diff --git a/android/app/src/main/res/layout/startpage_layout.xml b/android/app/src/main/res/layout/startpage_layout.xml
new file mode 100644
index 0000000..7310676
--- /dev/null
+++ b/android/app/src/main/res/layout/startpage_layout.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b20015e
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ updataDemo
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..319eb0c
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..03de1f7
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.3.2'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ mavenLocal()
+ jcenter()
+ maven {
+ // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
+ url "$rootDir/../node_modules/react-native/android"
+ }
+ }
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..1fd964e
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+android.useDeprecatedNdk=true
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..b5166da
Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..031b65e
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Aug 16 14:27:47 CST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/android/gradlew b/android/gradlew
new file mode 100644
index 0000000..91a7e26
--- /dev/null
+++ b/android/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/android/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/android/keystores/BUCK b/android/keystores/BUCK
new file mode 100644
index 0000000..88e4c31
--- /dev/null
+++ b/android/keystores/BUCK
@@ -0,0 +1,8 @@
+keystore(
+ name = "debug",
+ properties = "debug.keystore.properties",
+ store = "debug.keystore",
+ visibility = [
+ "PUBLIC",
+ ],
+)
diff --git a/android/keystores/debug.keystore.properties b/android/keystores/debug.keystore.properties
new file mode 100644
index 0000000..121bfb4
--- /dev/null
+++ b/android/keystores/debug.keystore.properties
@@ -0,0 +1,4 @@
+key.store=debug.keystore
+key.alias=androiddebugkey
+key.store.password=android
+key.alias.password=android
diff --git a/android/local.properties b/android/local.properties
new file mode 100644
index 0000000..a7364e9
--- /dev/null
+++ b/android/local.properties
@@ -0,0 +1,12 @@
+## This file is automatically generated by Android Studio.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+#Wed Aug 16 14:27:26 CST 2017
+ndk.dir=E\:\\androidSDK\\adt-bundle-windows-x86_64-20140702\\sdk\\ndk-bundle
+sdk.dir=E\:\\androidSDK\\adt-bundle-windows-x86_64-20140702\\sdk
diff --git a/android/mylibrary/.gitignore b/android/mylibrary/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/android/mylibrary/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/android/mylibrary/build.gradle b/android/mylibrary/build.gradle
new file mode 100644
index 0000000..d107b53
--- /dev/null
+++ b/android/mylibrary/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.3"
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 25
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ android {
+ lintOptions {
+ abortOnError false
+ }
+ }
+
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+
+ // From node_modules
+ compile 'com.liulishuo.filedownloader:library:1.6.3'
+ compile 'com.alibaba:fastjson:1.2.37'
+}
diff --git a/android/mylibrary/libs/armeabi-v7a/libApkPatchLibrary.so b/android/mylibrary/libs/armeabi-v7a/libApkPatchLibrary.so
new file mode 100644
index 0000000..a09078c
Binary files /dev/null and b/android/mylibrary/libs/armeabi-v7a/libApkPatchLibrary.so differ
diff --git a/android/mylibrary/libs/armeabi/libApkPatchLibrary.so b/android/mylibrary/libs/armeabi/libApkPatchLibrary.so
new file mode 100644
index 0000000..593df18
Binary files /dev/null and b/android/mylibrary/libs/armeabi/libApkPatchLibrary.so differ
diff --git a/android/mylibrary/libs/x86/libApkPatchLibrary.so b/android/mylibrary/libs/x86/libApkPatchLibrary.so
new file mode 100644
index 0000000..7979095
Binary files /dev/null and b/android/mylibrary/libs/x86/libApkPatchLibrary.so differ
diff --git a/android/mylibrary/mylibrary.iml b/android/mylibrary/mylibrary.iml
new file mode 100644
index 0000000..8efc9d2
--- /dev/null
+++ b/android/mylibrary/mylibrary.iml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/mylibrary/proguard-rules.pro b/android/mylibrary/proguard-rules.pro
new file mode 100644
index 0000000..58fe4c9
--- /dev/null
+++ b/android/mylibrary/proguard-rules.pro
@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in E:\androidSDK\adt-bundle-windows-x86_64-20140702\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/android/mylibrary/src/main/AndroidManifest.xml b/android/mylibrary/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ae102e1
--- /dev/null
+++ b/android/mylibrary/src/main/AndroidManifest.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/PatchUtils.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/PatchUtils.java
new file mode 100644
index 0000000..4580d27
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/PatchUtils.java
@@ -0,0 +1,51 @@
+package com.yyh.lib.bsdiff;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * APK Patch工具类
+ *
+ * @author yuyuhang
+ * @date 2016-1-26 下午1:10:40
+ */
+public class PatchUtils {
+
+ private static PatchUtils instance;
+
+ public static PatchUtils getInstance() {
+ if (instance == null)
+ instance = new PatchUtils();
+ return instance;
+ }
+
+ static {
+ System.loadLibrary("ApkPatchLibrary");
+ }
+
+ public synchronized void mergePatch(String oldbundlePath, String newbundlePath, String patchPath){
+ File destFile = new File(newbundlePath);
+ destFile.getParentFile().mkdirs();
+ try {
+ destFile.createNewFile();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ patch(oldbundlePath,newbundlePath,patchPath);
+ }
+
+
+
+ /**
+ * native方法 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath
+ * 返回:0,说明操作成功
+ * @param oldbundlePath
+ * 示例:/sdcard/old.apk
+ * @param newbundlePath
+ * 示例:/sdcard/new.apk
+ * @param patchPath
+ * 示例:/sdcard/xx.patch
+ * @return
+ */
+ public native int patch(String oldbundlePath, String newbundlePath, String patchPath);
+}
\ No newline at end of file
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/bean/RnCheckRes.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/bean/RnCheckRes.java
new file mode 100644
index 0000000..7966034
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/bean/RnCheckRes.java
@@ -0,0 +1,55 @@
+package com.yyh.lib.bsdiff.bean;
+
+import java.io.Serializable;
+
+/**
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class RnCheckRes implements Serializable {
+ private String zipPath = null;
+ private String version = null;
+ private String moduleName = null;
+ private String zipHash = null;
+ private String jsbundleHash = null;
+
+ public String getZipPath() {
+ return zipPath;
+ }
+
+ public void setZipPath(String zipPath) {
+ this.zipPath = zipPath;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ public void setModuleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ public String getZipHash() {
+ return zipHash;
+ }
+
+ public void setZipHash(String zipHash) {
+ this.zipHash = zipHash;
+ }
+
+ public String getJsbundleHash() {
+ return jsbundleHash;
+ }
+
+ public void setJsbundleHash(String jsbundleHash) {
+ this.jsbundleHash = jsbundleHash;
+ }
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/CopyModule.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/CopyModule.java
new file mode 100644
index 0000000..cc12bc3
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/CopyModule.java
@@ -0,0 +1,104 @@
+package com.yyh.lib.bsdiff.downloader;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+
+import com.yyh.lib.bsdiff.bean.RnCheckRes;
+import com.yyh.lib.bsdiff.utils.FileUtil;
+import com.yyh.lib.bsdiff.utils.LogUtils;
+import com.yyh.lib.bsdiff.utils.RNFilePathUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Lynn on 2017/8/20.
+ */
+
+public class CopyModule {
+
+
+ private Context mContext=null;
+ private RnVersionManager rnVersionManager=null;
+
+ public CopyModule(Context context){
+ this.mContext=context;
+ this.rnVersionManager=new RnVersionManager(context);
+ }
+
+ public void start(final Handler handler){
+ boolean mergedAssets =this.rnVersionManager.getSharedPreference().getString("lastVersion","").equals(getVersion(mContext));
+ if (!mergedAssets) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ merge(handler);
+ }
+ }).start();
+ }else {
+ handler.sendEmptyMessage(1); //通知主线程首次复制已完成
+ }
+ }
+
+ private void merge(Handler handler){
+ long time1=System.currentTimeMillis();
+ List rnCheckResList=new ArrayList();
+ RnCheckRes rnCheckRes1=new RnCheckRes();
+ rnCheckRes1.setModuleName("updataDemo");
+ rnCheckRes1.setVersion("1.0.0");
+ rnCheckResList.add(rnCheckRes1);
+
+ for (RnCheckRes rnCheckRes:rnCheckResList){
+ firstMergeAssets(rnCheckRes);
+ }
+ this.rnVersionManager.getSharedPreference().edit().putString("lastVersion",getVersion(mContext)).commit(); //putBoolean("mergedassets",true).commit();
+ handler.sendEmptyMessage(1); //通知主线程首次复制已完成
+ long time2=System.currentTimeMillis();
+ LogUtils.writeLog("首次的复制总耗时为 "+(time2-time1));
+ }
+
+ private void firstMergeAssets(RnCheckRes rnCheckRes) {
+ String moduleName=rnCheckRes.getModuleName();
+ try {
+ LogUtils.writeLog("开始复制 ");
+ FileUtil.deleteAll(RNFilePathUtils.getBundleRootPath(this.mContext)); //删除rn_bundle目录下所有文件
+ InputStream assestInput = this.mContext.getAssets().open(moduleName+".zip");
+ String dest = RNFilePathUtils.getBaseZipFile(this.mContext, moduleName);
+ if (FileUtil.copyFile(assestInput, dest)) { //copy插件包到宿主的安装目录下
+ FileUtil.unZipAll(
+ dest,
+ RNFilePathUtils.getBaseBundlePath(this.mContext, moduleName)
+ ); //资源解压到base文件夹下
+
+ //将bundle的描述信息以及版本信息写入sharedpreference
+ this.rnVersionManager.saveRnDescription(rnCheckRes);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+
+
+ public static String getVersion(Context context) {
+ try {
+ PackageManager manager = context.getPackageManager();
+ PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
+ return info.versionName;
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
+
+
+
+
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/MergeLastDownedFile.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/MergeLastDownedFile.java
new file mode 100644
index 0000000..a4062a0
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/MergeLastDownedFile.java
@@ -0,0 +1,94 @@
+package com.yyh.lib.bsdiff.downloader;
+
+import android.content.Context;
+import android.os.Handler;
+
+import com.yyh.lib.bsdiff.utils.FileUtil;
+import com.yyh.lib.bsdiff.utils.LogUtils;
+import com.yyh.lib.bsdiff.utils.RNFilePathUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 此类主要用于解压和复制上次下载的
+ * zip文件
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class MergeLastDownedFile {
+
+ private Context context = null;
+
+ private RnVersionManager rnVersionManager=null;
+
+ public MergeLastDownedFile(Context context){
+ if (this.context == null) {
+ this.context = context.getApplicationContext();
+ }
+ this.rnVersionManager=new RnVersionManager(this.context);
+ }
+
+
+
+ public void start(Handler handler) {
+ File file = new File(RNFilePathUtils.getBundleRootPath(this.context));
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ List listMoudleName = new ArrayList<>();
+ File[] childFiles = file.listFiles();
+ for (int i = 0; i < childFiles.length; i++) {
+ listMoudleName.add(childFiles[i].getName());
+ }
+ if (listMoudleName.size() == 0) {
+ handler.sendEmptyMessage(2); //表示完成了解压和复制
+ LogUtils.writeLog("解压和复制bundle总耗时为: 没有可解压和复制的文件");
+ return;
+ } else {
+ //开启一个线程来进行文件操作
+ start(listMoudleName,handler);
+ }
+ }
+ }
+ }
+
+
+ private void start(final List listMoudleName, final Handler handler) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ long time1=System.currentTimeMillis();
+ for (String moduleName : listMoudleName) {
+ copyAndUnzip(moduleName);
+ }
+ long time2=System.currentTimeMillis();
+ LogUtils.writeLog("解压和复制bundle总耗时为:"+(time2-time1));
+ handler.sendEmptyMessage(2); //表示完成了解压和复制
+ }
+ }).start();
+ }
+
+
+ private void copyAndUnzip(String moduleName) {
+ File file = new File(RNFilePathUtils.getBundleMergeFile(this.context, moduleName));
+ if (file.exists()) {
+ LogUtils.writeLog("存在可解压的文件以及需要复制的jsbundle");
+ FileUtil.unZipRes(
+ RNFilePathUtils.getBundleZipFile(this.context, moduleName),
+ RNFilePathUtils.getBundlePath(this.context, moduleName)
+ ); //资源覆盖解压
+
+ FileUtil.copyFile(
+ RNFilePathUtils.getBundleMergeFile(this.context, moduleName),
+ RNFilePathUtils.getBundleFile(this.context, moduleName)
+ ); //复制合并后的jsbundle
+ //此处应该读取版本信息存储在share文件中
+
+ FileUtil.deleteAll(RNFilePathUtils.getBundleMergePath(this.context, moduleName)); //删除merge文件夹下的东西
+ FileUtil.deleteAll(RNFilePathUtils.getBundlePatchPath(this.context, moduleName)); //删除patch文件夹下的东西
+
+ }
+ }
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/ModuleManager.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/ModuleManager.java
new file mode 100644
index 0000000..327f9a8
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/ModuleManager.java
@@ -0,0 +1,25 @@
+package com.yyh.lib.bsdiff.downloader;
+
+import android.content.Context;
+
+import com.yyh.lib.bsdiff.utils.RNFilePathUtils;
+
+import java.io.File;
+
+/**
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class ModuleManager {
+
+ public static String getMoudleJsBundleFile( Context mcontext,String moudleName){
+ File indexFile=new File(RNFilePathUtils.getBundleFile(mcontext,moudleName));
+ if(indexFile.exists()){
+ return RNFilePathUtils.getBundleFile(mcontext,moudleName);
+ }else {
+ return RNFilePathUtils.getBaseBundleFile(mcontext,moudleName);
+ }
+ }
+
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnModuleDiffUpdateService.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnModuleDiffUpdateService.java
new file mode 100644
index 0000000..c3673d3
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnModuleDiffUpdateService.java
@@ -0,0 +1,91 @@
+package com.yyh.lib.bsdiff.downloader;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import com.alibaba.fastjson.JSON;
+import com.yyh.lib.bsdiff.bean.RnCheckRes;
+import com.yyh.lib.bsdiff.utils.LogUtils;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class RnModuleDiffUpdateService extends Service {
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+
+ private Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case 1: //表示首次的资源复制已经完成
+ LogUtils.writeLog("首次的资源复制已经完成");
+ UnzipFile();
+ break;
+ case 2: //表示下载后的资源已经解压和复制
+ LogUtils.writeLog("表示下载后的资源已经解压和复制");
+ checkVersion();
+ break;
+
+ }
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ new CopyModule(this).start(this.handler);
+
+ }
+
+
+ /**
+ * 开始解压上次下载的patch文件
+ */
+ private void UnzipFile() {
+ new MergeLastDownedFile(this).start(this.handler);
+ }
+
+ /**
+ * 开始版本检测
+ */
+ private void checkVersion() {
+ //返回了结果之后
+ List ls = new ArrayList<>();
+
+ RnVersionManager rnVersionManager = new RnVersionManager(this);
+ HashMap versions = rnVersionManager.getRnVersion();
+
+ LogUtils.writeLog("版本检测数据结果" + JSON.toJSONString(versions));
+ if (versions.get("updataDemo").equals("1.0.0")) {
+ RnCheckRes rnCheckRes = new RnCheckRes();
+ rnCheckRes.setModuleName("updataDemo");
+ rnCheckRes.setVersion("1.0.1");
+ rnCheckRes.setJsbundleHash("c2c36ef32378c2fd61f38e9d36e1e87b");
+ rnCheckRes.setZipHash("de66af96ca496c4380ce174cba0bff9c");
+ rnCheckRes.setZipPath("http://192.168.10.221:8080/test/updataDemo.zip");
+ ls.add(rnCheckRes);
+ }
+ new RnModuleDownloader(this).startDown(ls);
+ }
+
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ LogUtils.writeLog("service onDestory");
+ }
+
+
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnModuleDownloader.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnModuleDownloader.java
new file mode 100644
index 0000000..e3a9c76
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnModuleDownloader.java
@@ -0,0 +1,111 @@
+package com.yyh.lib.bsdiff.downloader;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.alibaba.fastjson.JSON;
+import com.liulishuo.filedownloader.BaseDownloadTask;
+import com.liulishuo.filedownloader.FileDownloadQueueSet;
+import com.liulishuo.filedownloader.FileDownloadSampleListener;
+import com.liulishuo.filedownloader.FileDownloader;
+import com.yyh.lib.bsdiff.PatchUtils;
+import com.yyh.lib.bsdiff.bean.RnCheckRes;
+import com.yyh.lib.bsdiff.utils.FileMd5Utils;
+import com.yyh.lib.bsdiff.utils.FileUtil;
+import com.yyh.lib.bsdiff.utils.LogUtils;
+import com.yyh.lib.bsdiff.utils.RNFilePathUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class RnModuleDownloader {
+
+
+ private Context context = null;
+
+ public RnModuleDownloader(Context context) {
+ this.context = context.getApplicationContext();
+ }
+
+
+ /**
+ * 开始下载rn模块代码
+ * 此方法应该在rn的版本检测成功后调用
+ *
+ * @param resList
+ */
+ public void startDown(List resList) {
+ if(resList==null||resList.size()==0){
+ LogUtils.writeLog("没有可下载的文件 ");
+ return;
+ }
+
+ LogUtils.writeLog("开始执行下载模块的代码");
+ FileDownloadQueueSet queueSet = new FileDownloadQueueSet(new FileDownloadSampleListener() {
+ @Override
+ protected void completed(BaseDownloadTask task) {
+ super.completed(task);
+ LogUtils.writeLog("completed 下载完成 thread: "+Thread.currentThread().getName());
+ }
+
+ @Override
+ protected void blockComplete(BaseDownloadTask task) {
+ super.blockComplete(task);
+ String path = task.getPath();
+ LogUtils.writeLog("blockComplete 下载完成 本地存储路径为" + path +" thread: "+Thread.currentThread().getName());
+ RnCheckRes rnCheckRes = ((RnCheckRes) task.getTag());
+ if (FileMd5Utils.MD5File(path).equals(rnCheckRes.getZipHash())) { //比对zipmd5
+ unZipPatch(rnCheckRes);
+ } else { //删除patch文件夹下所有文件
+ LogUtils.writeLog("下载完文件后 进行MD5校验未通过 执行删除操作");
+ FileUtil.deleteAll(RNFilePathUtils.getBundlePatchPath(context, rnCheckRes.getModuleName()));
+ }
+ }
+ });
+
+ List tasks = new ArrayList<>();
+ for (RnCheckRes rnCheckRes : resList) {
+ if (!TextUtils.isEmpty(rnCheckRes.getZipPath())) {
+ String zipFilePath = RNFilePathUtils.getBundleZipFile(this.context, rnCheckRes.getModuleName());
+ tasks.add(FileDownloader.getImpl().create(rnCheckRes.getZipPath()).setPath(zipFilePath).setTag(rnCheckRes));
+ }
+ }
+ queueSet.disableCallbackProgressTimes(); // 由于是队列任务, 这里是我们假设了现在不需要每个任务都回调`FileDownloadListener#progress`, 我们只关系每个任务是否完成, 所以这里这样设置可以很有效的减少ipc.
+ queueSet.setAutoRetryTimes(1); // 所有任务在下载失败的时候都自动重试一次
+ queueSet.downloadTogether(tasks); // 并行执行该任务队列
+ queueSet.start();
+ }
+
+
+ /**
+ * 开始解压patch,并且合并patch文件
+ *
+ * @param rnCheckRes
+ */
+ private void unZipPatch(RnCheckRes rnCheckRes) {
+ String moduleName = rnCheckRes.getModuleName();
+ String jsbundleMd5 = rnCheckRes.getJsbundleHash();
+ FileUtil.unZipPatch(
+ RNFilePathUtils.getBundleZipFile(this.context, moduleName),
+ RNFilePathUtils.getBundlePatchPath(this.context, moduleName)); //解压到patch文件夹下
+ LogUtils.writeLog("解压完成 开始合并");
+ PatchUtils.getInstance().mergePatch( //合并jsbundle
+ RNFilePathUtils.getBaseBundleFile(this.context, moduleName),
+ RNFilePathUtils.getBundleMergeFile(this.context, moduleName),
+ RNFilePathUtils.getBundlePatchFile(this.context, moduleName)
+ );
+ if (!FileMd5Utils.MD5File(RNFilePathUtils.getBundleMergeFile(this.context, moduleName)).equals(jsbundleMd5)) {
+ FileUtil.deleteAll(RNFilePathUtils.getBundlePath(this.context, moduleName)); //删除下载的文件
+ LogUtils.writeLog("合并完文件后 进行MD5校验未通过 执行删除操作");
+ } else {
+ LogUtils.writeLog("合并完文件 并保存版本信息" + JSON.toJSONString(rnCheckRes));
+ // 保存版本号
+ new RnVersionManager(this.context).saveRnDescription(rnCheckRes); //保存版本信息
+ }
+ }
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnVersionManager.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnVersionManager.java
new file mode 100644
index 0000000..c232313
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/downloader/RnVersionManager.java
@@ -0,0 +1,143 @@
+package com.yyh.lib.bsdiff.downloader;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import com.yyh.lib.bsdiff.bean.RnCheckRes;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * Created by Lynn on 2017/8/20.
+ */
+
+public class RnVersionManager {
+
+ private String RN_VERSION_KEY = "rn_version_key";
+ private String RN_VERSION_SP = "rn_version_sp";
+ private Context context = null;
+
+ public RnVersionManager(Context context) {
+ this.context = context;
+ }
+
+ public synchronized void saveRnDescription(RnCheckRes rnCheckRes) {
+ if (rnCheckRes == null) {
+ return;
+ }
+ Hashtable oldHashTable = readRn(RN_VERSION_KEY);
+ if (oldHashTable == null) {
+ oldHashTable = new Hashtable<>();
+ }
+ oldHashTable.put(rnCheckRes.getModuleName(), rnCheckRes);
+ saveRn(RN_VERSION_KEY, oldHashTable);
+ }
+
+
+ public synchronized Hashtable getRnDescription() {
+ return readRn(RN_VERSION_KEY);
+ }
+
+ /**
+ * 获取所有的Rn模块的版本信息
+ * 返回一个hashmap,map的key是模块的名字
+ * map的value是rn的版本号
+ * @return
+ */
+ public synchronized HashMap getRnVersion() {
+ HashMap hashMap = new HashMap<>();
+ Hashtable hashtable = readRn(RN_VERSION_KEY);
+ if (hashtable != null) {
+ for (Map.Entry entry : hashtable.entrySet()) {
+ hashMap.put(entry.getKey(), entry.getValue().getVersion());
+ }
+ }
+ return hashMap;
+ }
+
+
+ public SharedPreferences getSharedPreference() {
+ return this.context.getApplicationContext().getSharedPreferences(RN_VERSION_SP, Context.MODE_PRIVATE);
+ }
+
+
+ private synchronized boolean saveRn(String key, Hashtable rns) {
+
+ ObjectOutputStream objectOutputStream = null;
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ try {
+ objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
+ objectOutputStream.writeObject(rns);
+ objectOutputStream.flush();
+
+ byte[] data = byteArrayOutputStream.toByteArray();
+ String list = Base64.encodeToString(data, Base64.DEFAULT);
+
+ getSharedPreference().edit().putString(key, list).commit();
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (objectOutputStream != null) {
+ try {
+ objectOutputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (byteArrayOutputStream != null) {
+ try {
+ byteArrayOutputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return false;
+ }
+
+ private synchronized Hashtable readRn(String key) {
+ String list = getSharedPreference().getString(key, "");
+ Serializable object = null;
+ if (!TextUtils.isEmpty(list)) {
+ ByteArrayInputStream byteArrayInputStream = null;
+ ObjectInputStream objectInputStream = null;
+ try {
+ byteArrayInputStream = new ByteArrayInputStream(Base64.decode(list, Base64.DEFAULT));
+ objectInputStream = new ObjectInputStream(byteArrayInputStream);
+ object = (Serializable) objectInputStream.readObject();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (objectInputStream != null) {
+ try {
+ objectInputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (byteArrayInputStream != null) {
+ try {
+ byteArrayInputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ return (Hashtable) object;
+ }
+
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/FileMd5Utils.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/FileMd5Utils.java
new file mode 100644
index 0000000..3aad6d5
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/FileMd5Utils.java
@@ -0,0 +1,81 @@
+package com.yyh.lib.bsdiff.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+
+/**
+ * Created by Lynn on 2017/8/17.
+ */
+
+public class FileMd5Utils {
+
+ static char hexdigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ /**
+ * md5文件生成摘要
+ *
+ * @param filePath
+ * @return
+ * @see [类、类#方法、类#成员]
+ */
+ public static String MD5File(String filePath) {
+ File file=new File(filePath);
+ FileInputStream fis = null;
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ fis = new FileInputStream(file);
+ byte[] buffer = new byte[2048];
+ int length = -1;
+ while ((length = fis.read(buffer)) != -1) {
+ md.update(buffer, 0, length);
+ }
+ // 32位加密
+ byte[] b = md.digest();
+ return byteToHexString(b);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ } finally {
+ try {
+ fis.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+
+ /**
+ * @param tmp
+ * @return
+ * @see [类、类#方法、类#成员]
+ */
+ private static String byteToHexString(byte[] tmp) {
+ String s;
+ // 用字节表示就是 16 个字节
+ char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话,使用两个字符,
+ // 所以表示成 16 进制需要 32 个字符
+ // 表示转换结果中对应的字符位置
+ int k = 0;
+ for (int i = 0; i < 16; i++) {
+ // 从第一个字节开始,对 MD5 的每一个字节
+ // 转换成 16 进制字符的转换
+ // 取第 i 个字节
+ byte byte0 = tmp[i];
+ // 取字节中高 4 位的数字转换,
+ str[k++] = hexdigits[byte0 >>> 4 & 0xf];
+ // >>> 为逻辑右移,将符号位一起右移
+ // 取字节中低 4 位的数字转换
+ str[k++] = hexdigits[byte0 & 0xf];
+ }
+ // 换后的结果转换为字符串
+ s = new String(str);
+ return s;
+ }
+
+
+
+
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/FileUtil.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/FileUtil.java
new file mode 100644
index 0000000..577ca60
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/FileUtil.java
@@ -0,0 +1,374 @@
+package com.yyh.lib.bsdiff.utils;
+
+import android.text.TextUtils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class FileUtil {
+
+ private static final boolean DEBUG = true;
+
+ public static boolean copyFile(String source, String dest) {
+ try {
+ return copyFile(new FileInputStream(new File(source)), dest);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public static boolean copyFile(final InputStream inputStream, String dest) {
+ FileOutputStream oputStream = null;
+ try {
+ File destFile = new File(dest);
+ destFile.getParentFile().mkdirs();
+ destFile.createNewFile();
+
+ oputStream = new FileOutputStream(destFile);
+ byte[] bb = new byte[10 * 1024];
+ int len = 0;
+ while ((len = inputStream.read(bb)) != -1) {
+ oputStream.write(bb, 0, len);
+ }
+ oputStream.flush();
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (oputStream != null) {
+ try {
+ oputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public static synchronized void unZipAll(String zipFile, String aimdir) {
+ File tempDir=new File(aimdir);
+ if (!tempDir.exists()) {
+ tempDir.mkdirs();
+ }
+ ZipFile zfile = null;
+ BufferedOutputStream fos = null;
+ BufferedInputStream bis = null;
+
+ LogUtils.writeLog("开始解压");
+ try {
+ zfile = new ZipFile(zipFile);
+ ZipEntry ze = null;
+ Enumeration zList = zfile.entries();
+ while (zList.hasMoreElements()) {
+ ze = (ZipEntry) zList.nextElement();
+ String relativePath = ze.getName();
+
+ if (ze.isDirectory()) {
+ File folder = new File(tempDir, relativePath);
+ if (DEBUG) {
+ LogUtils.writeLog("isDirectory : "
+ + folder.getAbsolutePath());
+ }
+ if (!folder.exists()) {
+ folder.mkdirs();
+ }
+
+ } else {
+ File targetFile = new File(tempDir, relativePath);
+ if (!targetFile.getParentFile().exists()) {
+ targetFile.getParentFile().mkdirs();
+ }
+ targetFile.createNewFile();
+
+ fos = new BufferedOutputStream(new FileOutputStream(
+ targetFile));
+ bis = new BufferedInputStream(zfile.getInputStream(ze));
+ byte[] buffer = new byte[2 * 1024];
+ int count = -1;
+ while ((count = bis.read(buffer)) != -1) {
+ fos.write(buffer, 0, count);
+ fos.flush();
+ }
+ fos.close();
+ fos = null;
+ bis.close();
+ bis = null;
+
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtils.writeLog("解压出现异常");
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (bis != null) {
+ try {
+ bis.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (zfile != null) {
+ try {
+ zfile.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static synchronized void unZipRes(String zipFile, String aimdir) {
+ File tempDir=new File(aimdir);
+ if (!tempDir.exists()) {
+ tempDir.mkdirs();
+ }
+ ZipFile zfile = null;
+ BufferedOutputStream fos = null;
+ BufferedInputStream bis = null;
+
+ LogUtils.writeLog("开始解压");
+ try {
+ zfile = new ZipFile(zipFile);
+ ZipEntry ze = null;
+ Enumeration zList = zfile.entries();
+ while (zList.hasMoreElements()) {
+ ze = (ZipEntry) zList.nextElement();
+ String relativePath = ze.getName();
+
+ if (relativePath.startsWith("index")) {
+ if (DEBUG) {
+ LogUtils.writeLog("relativePath : " + relativePath);
+ }
+ continue;
+ }
+
+ if (ze.isDirectory()) {
+ File folder = new File(tempDir, relativePath);
+ if (DEBUG) {
+ LogUtils.writeLog("isDirectory : "
+ + folder.getAbsolutePath());
+ }
+ if (!folder.exists()) {
+ folder.mkdirs();
+ }
+
+ } else {
+ File targetFile = new File(tempDir, relativePath);
+ if (!targetFile.getParentFile().exists()) {
+ targetFile.getParentFile().mkdirs();
+ }
+ targetFile.createNewFile();
+
+ fos = new BufferedOutputStream(new FileOutputStream(
+ targetFile));
+ bis = new BufferedInputStream(zfile.getInputStream(ze));
+ byte[] buffer = new byte[2 * 1024];
+ int count = -1;
+ while ((count = bis.read(buffer)) != -1) {
+ fos.write(buffer, 0, count);
+ fos.flush();
+ }
+ fos.close();
+ fos = null;
+ bis.close();
+ bis = null;
+
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtils.writeLog("解压出现异常");
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (bis != null) {
+ try {
+ bis.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (zfile != null) {
+ try {
+ zfile.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static synchronized void unZipPatch(String apkFile, String aimdir) {
+ File tempDir=new File(aimdir);
+ if (!tempDir.exists()) {
+ tempDir.mkdirs();
+ }
+ ZipFile zfile = null;
+ BufferedOutputStream fos = null;
+ BufferedInputStream bis = null;
+
+ LogUtils.writeLog("开始解压");
+ try {
+ zfile = new ZipFile(apkFile);
+ ZipEntry ze = null;
+ Enumeration zList = zfile.entries();
+ while (zList.hasMoreElements()) {
+ ze = (ZipEntry) zList.nextElement();
+ String relativePath = ze.getName();
+ if (!ze.isDirectory()) {
+ if (relativePath.endsWith("patch")) {
+ File targetFile = new File(tempDir, relativePath);
+
+ if (!targetFile.getParentFile().exists()) {
+ targetFile.getParentFile().mkdirs();
+ }
+ targetFile.createNewFile();
+
+ fos = new BufferedOutputStream(new FileOutputStream(
+ targetFile));
+ bis = new BufferedInputStream(zfile.getInputStream(ze));
+ byte[] buffer = new byte[2 * 1024];
+ int count = -1;
+ while ((count = bis.read(buffer)) != -1) {
+ fos.write(buffer, 0, count);
+ fos.flush();
+ }
+ fos.close();
+ fos = null;
+ bis.close();
+ bis = null;
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+
+ LogUtils.writeLog("解压出现异常");
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (bis != null) {
+ try {
+ bis.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (zfile != null) {
+ try {
+ zfile.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * 从文本文件中读取文本
+ *
+ * @param path
+ * @return
+ * @throws IOException
+ */
+ public static String readFile(String path) throws IOException {
+ StringBuilder contentBuilder = new StringBuilder();
+ File file = new File(path);
+ if (file.exists()) {
+ FileInputStream fileInputStream = new FileInputStream(file);
+ InputStreamReader inStreamReader = new InputStreamReader(fileInputStream);
+ BufferedReader reader = new BufferedReader(inStreamReader);
+ String line;
+ while ((line = reader.readLine()) != null) {
+ contentBuilder.append(line);
+ }
+ reader.close();
+ inStreamReader.close();
+ }
+ return contentBuilder.toString().trim();
+ }
+
+
+ /**
+ * 向文本文件中写入文本
+ * @param path
+ * @return
+ * @throws IOException
+ */
+ public static void writeFile(String path, String content) throws IOException {
+ if (!TextUtils.isEmpty(content)) {
+ File file = new File(path);
+ if (file.exists()) {
+ file.delete();
+ } else {
+ file.getParentFile().mkdirs();
+ }
+ file.createNewFile();
+
+ FileWriter fileWriter = new FileWriter(file);
+ fileWriter.write(content);
+ fileWriter.flush();
+ fileWriter.close();
+ }
+ }
+
+
+ /**
+ * 递归删除文件及文件夹
+ * @param path
+ * @return
+ */
+ public static boolean deleteAll(String path) {
+ File file=new File(path);
+ if (file.isDirectory()) {
+ File[] childFiles = file.listFiles();
+ if (childFiles != null && childFiles.length > 0) {
+ for (int i = 0; i < childFiles.length; i++) {
+ deleteAll(childFiles[i].getAbsolutePath());
+ }
+ }
+ }
+ return file.delete();
+ }
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/LogUtils.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/LogUtils.java
new file mode 100644
index 0000000..7fa34a1
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/LogUtils.java
@@ -0,0 +1,18 @@
+package com.yyh.lib.bsdiff.utils;
+
+/**
+ * Created by Lynn on 2017/8/21.
+ */
+
+public class LogUtils {
+
+ public static boolean isDebug=true;
+ public static String TAG="";
+
+ public static void writeLog(String msg){
+
+ if(isDebug){
+ System.out.println(TAG+msg);
+ }
+ }
+}
diff --git a/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/RNFilePathUtils.java b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/RNFilePathUtils.java
new file mode 100644
index 0000000..6ac3aa7
--- /dev/null
+++ b/android/mylibrary/src/main/java/com/yyh/lib/bsdiff/utils/RNFilePathUtils.java
@@ -0,0 +1,79 @@
+package com.yyh.lib.bsdiff.utils;
+
+import android.content.Context;
+
+import java.io.File;
+
+/**
+ * Created by Lynn on 2017/8/8.
+ */
+
+public class RNFilePathUtils {
+
+ public static String INDEX_BUNDLE_NAME="index.android.bundle";
+ public static String BASE_BUNDLE_NAME="index.android.bundle";
+ public static String BASE_BUNDLE_ZIP="base.zip";
+
+
+ public static String MERGE_BUNDLE_NAME="merge.android.bundle";
+ public static String BUNDLE_PATCH_NAME="bundle.patch";
+ public static String PATCH_ZIP_NAME="patch.zip";
+
+
+
+ public static String getBundleRootPath(Context context){
+ return context.getApplicationContext().getCacheDir().getParent()+File.separator+"rn_bundle";
+ }
+
+
+ public static String getBundlePath(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"index";
+ }
+ public static String getBundleFile(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"index"+File.separator+INDEX_BUNDLE_NAME;
+ }
+
+ /**
+ * 获取patch的路径
+ * @param context
+ * @return
+ */
+ public static String getBundlePatchPath(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"patch";
+ }
+
+ public static String getBundlePatchFile(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"patch"+File.separator+BUNDLE_PATCH_NAME;
+ }
+ public static String getBundleZipFile(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"patch"+File.separator+PATCH_ZIP_NAME;
+ }
+
+ /**
+ * 获取用于存放合并文件的路径
+ * @param context
+ * @return
+ */
+ public static String getBundleMergePath(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"merge";
+ }
+ public static String getBundleMergeFile(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"merge"+File.separator+MERGE_BUNDLE_NAME;
+ }
+ /**
+ * 获取存储基线包的路径
+ * @param context
+ * @return
+ */
+ public static String getBaseBundlePath(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"base";
+ }
+
+ public static String getBaseBundleFile(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"base"+File.separator+BASE_BUNDLE_NAME;
+ }
+
+ public static String getBaseZipFile(Context context,String moduleName){
+ return getBundleRootPath(context)+File.separator+moduleName+File.separator+"base"+File.separator+BASE_BUNDLE_ZIP;
+ }
+}
diff --git a/android/mylibrary/src/main/res/values/strings.xml b/android/mylibrary/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e3a7072
--- /dev/null
+++ b/android/mylibrary/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ My Library
+
diff --git a/android/package.json b/android/package.json
new file mode 100644
index 0000000..6a1c7cb
--- /dev/null
+++ b/android/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "react-native-diff-update",
+ "version": "1.0.0",
+ "description": "React native android端增量更新,支持多入口多业务.",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/xagreenpoint/LDReactNativeDiffUpdate.git"
+ },
+ "keywords": [
+ "Rn增量更新"
+ ],
+ "author": "leadeon",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/xagreenpoint/LDReactNativeDiffUpdate/issues"
+ },
+ "homepage": "https://github.com/xagreenpoint/LDReactNativeDiffUpdate#readme"
+}
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..1d0de27
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1,3 @@
+rootProject.name = 'updataDemo'
+
+include ':app', ':mylibrary'
diff --git a/android/updataDemo.iml b/android/updataDemo.iml
new file mode 100644
index 0000000..e790760
--- /dev/null
+++ b/android/updataDemo.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file