1.IcLauncher 未完成右滑动的时候没有显示APP列表。
authorkfl_614 <kfl_614@163.com>
Sun, 22 Mar 2020 11:05:19 +0000 (19:05 +0800)
committerkfl_614 <kfl_614@163.com>
Sun, 22 Mar 2020 11:05:19 +0000 (19:05 +0800)
Signed-off-by: kfl_614 <kfl_614@163.com>
135 files changed:
.gitignore [new file with mode: 0644]
.idea/.name [new file with mode: 0644]
.idea/codeStyles/Project.xml [new file with mode: 0644]
.idea/gradle.xml [new file with mode: 0644]
.idea/misc.xml [new file with mode: 0644]
.idea/runConfigurations.xml [new file with mode: 0644]
.idea/vcs.xml [new file with mode: 0644]
app/.gitignore [new file with mode: 0644]
app/build.gradle [new file with mode: 0644]
app/proguard-rules.pro [new file with mode: 0644]
app/src/androidTest/java/com/ic/launcher/ExampleInstrumentedTest.java [new file with mode: 0644]
app/src/main/AndroidManifest.xml [new file with mode: 0644]
app/src/main/java/com/ic/launcher/IcLauncherApplication.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/MainActivity.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/adapter/AppInfoAdapter.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/configure/l02/L02AppInfo.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/configure/l02/L02Icon.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/entity/AppInfoEntity.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/fragment/AppListFragment.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/fragment/L02MainFragment.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/fragment/l02/L02StatusBarFragment.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/fragment/l02/L02WatchFragment.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/listener/IChangeMainFragmentListener.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/listener/ICheckAppItemListener.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/listener/MainClockGestureDetectorImpl.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/mode/AppListModel.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/mode/StateBarModel.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/mode/WatchFaceModel.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/presenter/AppListPresenter.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/presenter/BatteryPresenter.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/presenter/PhoneStatePresenter.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/presenter/QueryThread.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/presenter/QueryTrafficPooler.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/presenter/TimeDatePresenter.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/util/IcLog.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/util/OsUtil.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/util/ServiceUtil.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/widget/ClockWatchView.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/widget/WidgetBatteryStateView.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/widget/WidgetPhoneStateView.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/widget/WidgetTimeImageView.java [new file with mode: 0644]
app/src/main/java/com/ic/launcher/widget/WidgetTimeTextView.java [new file with mode: 0644]
app/src/main/res/drawable-v24/ic_launcher_foreground.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_account_circle.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_launcher_background.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_no_sim_card.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_sim_locking.xml [new file with mode: 0644]
app/src/main/res/drawable/l02_battery_charging_anim.xml [new file with mode: 0644]
app/src/main/res/layout/activity_main.xml [new file with mode: 0644]
app/src/main/res/layout/fragment_app_list.xml [new file with mode: 0644]
app/src/main/res/layout/fragment_l02_main.xml [new file with mode: 0644]
app/src/main/res/layout/fragment_l02_status_bar.xml [new file with mode: 0644]
app/src/main/res/layout/fragment_l02_watch.xml [new file with mode: 0644]
app/src/main/res/layout/item_app_layout.xml [new file with mode: 0644]
app/src/main/res/layout/widget_battery_state_layout.xml [new file with mode: 0644]
app/src/main/res/layout/widget_phone_state_layout.xml [new file with mode: 0644]
app/src/main/res/layout/widget_time_image_layout.xml [new file with mode: 0644]
app/src/main/res/layout/widget_time_text_layout.xml [new file with mode: 0644]
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml [new file with mode: 0644]
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml [new file with mode: 0644]
app/src/main/res/mipmap-hdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-hdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_heartrate_icon.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_0.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_1.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_2.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_3.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_4.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_5.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_6.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_7.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_8.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_hour_9.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_0.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_1.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_2.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_3.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_4.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_5.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_6.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_7.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_8.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_minutes_9.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_pedometer.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/clockl02_time_colon.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_albumn_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_alipay_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_camera_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_contacts_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_dialer_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_heartrate_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_pedometer_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_settings_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_sms_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_talk_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/icon_weather_l02.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_battery_0.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_battery_1.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_battery_2.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_battery_3.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_battery_4.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_battery_5.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_data_transport_0.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_data_transport_1.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_data_transport_2.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_data_transport_3.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_phone_type_4g.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_signal_0.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_signal_1.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_signal_2.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_signal_3.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_signal_4.png [new file with mode: 0644]
app/src/main/res/mipmap-ldpi/l02_signal_x.png [new file with mode: 0644]
app/src/main/res/mipmap-mdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-mdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-mdpi/l02_signal_nosim.png [new file with mode: 0644]
app/src/main/res/mipmap-xhdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-xxhdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png [new file with mode: 0644]
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png [new file with mode: 0644]
app/src/main/res/values/attr.xml [new file with mode: 0644]
app/src/main/res/values/colors.xml [new file with mode: 0644]
app/src/main/res/values/dimens.xml [new file with mode: 0644]
app/src/main/res/values/strings.xml [new file with mode: 0644]
app/src/main/res/values/styles.xml [new file with mode: 0644]
app/src/test/java/com/ic/launcher/ExampleUnitTest.java [new file with mode: 0644]
build.gradle [new file with mode: 0644]
gradle.properties [new file with mode: 0644]
gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
gradlew [new file with mode: 0644]
gradlew.bat [new file with mode: 0644]
settings.gradle [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..603b140
--- /dev/null
@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
diff --git a/.idea/.name b/.idea/.name
new file mode 100644 (file)
index 0000000..d400110
--- /dev/null
@@ -0,0 +1 @@
+IcLauncher
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644 (file)
index 0000000..681f41a
--- /dev/null
@@ -0,0 +1,116 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <codeStyleSettings language="XML">
+      <indentOptions>
+        <option name="CONTINUATION_INDENT_SIZE" value="4" />
+      </indentOptions>
+      <arrangement>
+        <rules>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:android</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:id</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>style</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>ANDROID_ATTRIBUTE_ORDER</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>.*</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+        </rules>
+      </arrangement>
+    </codeStyleSettings>
+  </code_scheme>
+</component>
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644 (file)
index 0000000..d291b3d
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <compositeConfiguration>
+          <compositeBuild compositeDefinitionSource="SCRIPT" />
+        </compositeConfiguration>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="resolveModulePerSourceSet" value="false" />
+        <option name="testRunner" value="PLATFORM" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644 (file)
index 0000000..687d49e
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+    <option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="12">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+          <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+          <item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
+          <item index="6" class="java.lang.String" itemvalue="android.annotation.Nullable" />
+          <item index="7" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
+          <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
+          <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
+          <item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
+          <item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="11">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+          <item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
+          <item index="5" class="java.lang.String" itemvalue="android.annotation.NonNull" />
+          <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
+          <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
+          <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
+          <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
+          <item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644 (file)
index 0000000..7f68460
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644 (file)
index 0000000..94a25f7
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644 (file)
index 0000000..796b96d
--- /dev/null
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644 (file)
index 0000000..bb500df
--- /dev/null
@@ -0,0 +1,58 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 29
+    buildToolsVersion "29.0.2"
+    defaultConfig {
+        applicationId "com.ic.launcher"
+        minSdkVersion 19
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+    }
+
+    dataBinding {
+        enabled = true
+    }
+
+    //使用JDK1.8
+    compileOptions {
+        targetCompatibility JavaVersion.VERSION_1_8
+        sourceCompatibility JavaVersion.VERSION_1_8
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.appcompat:appcompat:1.1.0'
+    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+
+    // ViewModel
+    implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
+    // LiveData
+    implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"
+    // Saved state module for ViewModel
+    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0"
+    // alternately - if using Java8, use the following instead of lifecycle-compiler
+    implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
+    // optional - ReactiveStreams support for LiveData
+    implementation "androidx.lifecycle:lifecycle-reactivestreams:2.2.0"
+
+    //recyclerview
+    implementation "androidx.recyclerview:recyclerview:1.1.0"
+    implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
+
+    //1.2.0-alpha05
+    implementation "com.google.android.material:material:1.2.0-alpha05"
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644 (file)
index 0000000..f1b4245
--- /dev/null
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# 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/app/src/androidTest/java/com/ic/launcher/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/ic/launcher/ExampleInstrumentedTest.java
new file mode 100644 (file)
index 0000000..1128a6a
--- /dev/null
@@ -0,0 +1,27 @@
+package com.ic.launcher;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+        assertEquals("com.ic.launcher", appContext.getPackageName());
+    }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..5184a30
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.ic.launcher">
+
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+    <application
+        android:name=".IcLauncherApplication"
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+
+        <activity android:name=".MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.intent.action.VIEW" />
+
+                <category android:name="android.intent.category.HOME" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/com/ic/launcher/IcLauncherApplication.java b/app/src/main/java/com/ic/launcher/IcLauncherApplication.java
new file mode 100644 (file)
index 0000000..134dc0c
--- /dev/null
@@ -0,0 +1,42 @@
+package com.ic.launcher;
+
+import android.app.Application;
+
+import com.ic.launcher.presenter.AppListPresenter;
+import com.ic.launcher.presenter.BatteryPresenter;
+import com.ic.launcher.presenter.PhoneStatePresenter;
+import com.ic.launcher.presenter.TimeDatePresenter;
+import com.ic.launcher.util.IcLog;
+
+public class IcLauncherApplication extends Application {
+
+    private PhoneStatePresenter mPhoneState;
+    private BatteryPresenter  mBatteryPresenter;
+    private TimeDatePresenter timeDatePresenter;
+    private AppListPresenter appListPresenter;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        IcLog.setLogHead("IcLauncher");
+
+        mPhoneState = new PhoneStatePresenter(this);
+        mBatteryPresenter = new BatteryPresenter(this);
+        timeDatePresenter = new TimeDatePresenter(this);
+        appListPresenter = new AppListPresenter(this);
+    }
+
+    public PhoneStatePresenter getPhoneStatePresenter() {
+        return mPhoneState;
+    }
+    public BatteryPresenter getBatterPresenter() {
+        return mBatteryPresenter;
+    }
+    public TimeDatePresenter getTimeDatePresenter() {
+        return timeDatePresenter;
+    }
+    public AppListPresenter getAppListPresenter() {
+        return appListPresenter;
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/MainActivity.java b/app/src/main/java/com/ic/launcher/MainActivity.java
new file mode 100644 (file)
index 0000000..f47e5d8
--- /dev/null
@@ -0,0 +1,86 @@
+package com.ic.launcher;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import android.os.Bundle;
+
+import com.ic.launcher.fragment.AppListFragment;
+import com.ic.launcher.fragment.L02MainFragment;
+import com.ic.launcher.listener.IChangeMainFragmentListener;
+import com.ic.launcher.listener.MainClockGestureDetectorImpl;
+import com.ic.launcher.util.ServiceUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class MainActivity extends AppCompatActivity implements
+        MainClockGestureDetectorImpl.OnClockGestureFlingListener,
+        IChangeMainFragmentListener {
+
+    private FragmentManager fragmentManager;
+
+    private List<Fragment> mAddFt;
+
+    private L02MainFragment l02MainFt;
+    private AppListFragment appListFt;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        mAddFt = new ArrayList<>();
+        fragmentManager = getSupportFragmentManager();
+
+        crateFragment();
+        commitFragment(l02MainFt);
+
+        ServiceUtil.startServiceUtil(getApplicationContext(),
+                "com.ic.action.WORK_SERVICE",
+                getPackageName());
+    }
+
+    @Override
+    public void onDirection(int flag) {
+        switch (flag) {
+            case 1:
+                //左滑
+                commitFragment(appListFt);
+                break;
+            case 2:
+                //右滑
+                break;
+        }
+    }
+
+    @Override
+    public void onChangeMain() {
+        //app列表已滑动到第一个或者第二个,需要切换到主main
+        commitFragment(l02MainFt);
+    }
+
+    private void crateFragment() {
+        l02MainFt = L02MainFragment.newInstance();
+        appListFt = AppListFragment.newInstance();
+    }
+
+    private void commitFragment(Fragment fragment) {
+        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+        for (int i = 0; i < mAddFt.size(); i++) {
+            fragmentTransaction.hide(mAddFt.get(i));
+        }
+
+        if (fragment.isAdded()) {
+            fragmentTransaction.show(fragment);
+        } else {
+            mAddFt.add(fragment);
+            fragmentTransaction.add(R.id.main_content_fl, fragment);
+        }
+
+        fragmentTransaction.commit();
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/adapter/AppInfoAdapter.java b/app/src/main/java/com/ic/launcher/adapter/AppInfoAdapter.java
new file mode 100644 (file)
index 0000000..ecdc53d
--- /dev/null
@@ -0,0 +1,72 @@
+package com.ic.launcher.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.ic.launcher.databinding.ItemAppLayoutBinding;
+import com.ic.launcher.entity.AppInfoEntity;
+import com.ic.launcher.listener.ICheckAppItemListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AppInfoAdapter extends RecyclerView.Adapter<AppInfoAdapter.AppHolder> {
+    private static final String TAG = "AppInfoAdapter";
+
+    private Context mContext;
+    private List<AppInfoEntity> appArray;
+    private ICheckAppItemListener mListener;
+
+    public AppInfoAdapter(Context context,ICheckAppItemListener listener) {
+        this.mContext = context;
+        appArray = new ArrayList<>();
+        this.mListener = listener;
+    }
+
+    public void updateAppInfoList(List<AppInfoEntity> list){
+        appArray.clear();
+        appArray.addAll(list);
+        notifyDataSetChanged();
+    }
+
+    @NonNull
+    @Override
+    public AppHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        return new AppHolder(ItemAppLayoutBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull AppHolder holder, int position) {
+        holder.bindAppInfo(mContext, appArray.get(position),mListener,position);
+    }
+
+    @Override
+    public int getItemCount() {
+        return appArray.size();
+    }
+
+    static class AppHolder extends RecyclerView.ViewHolder {
+        private ItemAppLayoutBinding binding = null;
+
+        public AppHolder(@NonNull ItemAppLayoutBinding itemView) {
+            super(itemView.getRoot());
+            binding = itemView;
+        }
+
+
+        public void bindAppInfo(Context context, AppInfoEntity entity, ICheckAppItemListener listener,int pos) {
+            if (binding == null || entity == null) {
+                return;
+            }
+            binding.setClick(listener);
+            binding.setPos(pos);
+            binding.appIconIv.setImageResource(entity.getAppIconResId());
+            binding.setAppTitle(context.getString(entity.getAppTitleResId()));
+            binding.executePendingBindings();
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/configure/l02/L02AppInfo.java b/app/src/main/java/com/ic/launcher/configure/l02/L02AppInfo.java
new file mode 100644 (file)
index 0000000..239ad06
--- /dev/null
@@ -0,0 +1,52 @@
+package com.ic.launcher.configure.l02;
+
+import android.graphics.Color;
+
+import com.ic.launcher.R;
+import com.ic.launcher.entity.AppInfoEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class L02AppInfo {
+
+    private static final int BACK_COLOUR = Color.parseColor("#000000");
+
+    public static final List<AppInfoEntity> mL02DefaultAppList = new ArrayList<AppInfoEntity>() {
+        {
+            //联系人
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_contacts_l02, R.string.app_name_contacts,
+                    "com.enqualcomm.imessage", "com.enqualcomm.imessage.ui.PhoneDirectoryActivity"));
+            //拨号
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_dialer_l02, R.string.app_name_dialer,
+                    "com.ic.dial", "com.ic.dial.MainActivity"));
+            //运动
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_pedometer_l02, R.string.app_name_motion,
+                    "com.ic.hardware", "com.ic.hardware.PedometerActivity"));
+            //微聊
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_talk_l02, R.string.app_name_talk,
+                    "", ""));
+            //天气
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_weather_l02, R.string.app_name_weather,
+                    "com.ic.hardware", "com.ic.hardware.WeatherActivity"));
+            //心率
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_heartrate_l02, R.string.app_name_heart,
+                    "com.ic.hardware", "com.ic.hardware.BloodActivity"));
+            //支付包
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_alipay_l02, R.string.app_name_alipay,
+                    "com.eg.android.AlipayGphone", "com.alipay.watch.ui.MainActivity"));
+            //相机
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_camera_l02, R.string.app_name_camera,
+                    "com.eqc.camera", "com.eqc.camera.TakePictureActivity"));
+            //相册
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_albumn_l02, R.string.app_name_album,
+                    "com.eqc.gallery", "com.eqc.gallery.ui.LocalAlbumDetail"));
+            //短信
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_sms_l02, R.string.app_name_short_message,
+                    "com.zmapp.sms", "com.zmapp.sms.MainActivity"));
+            //设置
+            add(new AppInfoEntity(BACK_COLOUR, R.mipmap.icon_settings_l02, R.string.app_name_setting,
+                    "com.eqc.settings", "com.eqc.settings.MainActivity"));
+        }
+    };
+}
diff --git a/app/src/main/java/com/ic/launcher/configure/l02/L02Icon.java b/app/src/main/java/com/ic/launcher/configure/l02/L02Icon.java
new file mode 100644 (file)
index 0000000..ba58d9e
--- /dev/null
@@ -0,0 +1,66 @@
+package com.ic.launcher.configure.l02;
+
+import com.ic.launcher.R;
+
+public class L02Icon {
+
+    //L02 信号图片
+    public static int[] l02SignalResId = new int[]{
+            R.mipmap.l02_signal_nosim,
+            R.drawable.ic_sim_locking,
+            R.mipmap.l02_signal_x,
+            R.mipmap.l02_signal_1,
+            R.mipmap.l02_signal_2,
+            R.mipmap.l02_signal_3,
+            R.mipmap.l02_signal_4
+    };
+
+    //L02 信号图片
+    public static int[] l02PhoneTypeResId = new int[]{
+            R.mipmap.l02_phone_type_4g
+    };
+
+    //L02 信号图片
+    public static int[] l02TransportResId = new int[]{
+            R.mipmap.l02_data_transport_0,
+            R.mipmap.l02_data_transport_1,
+            R.mipmap.l02_data_transport_2,
+            R.mipmap.l02_data_transport_3
+    };
+
+    //L02 信号图片
+    public static int[] l02BatteryResId = new int[]{
+            R.mipmap.l02_battery_0,
+            R.mipmap.l02_battery_1,
+            R.mipmap.l02_battery_2,
+            R.mipmap.l02_battery_3,
+            R.mipmap.l02_battery_4,
+            R.mipmap.l02_battery_5
+    };
+
+    public static int[] l02TimeHourImage = new int[]{
+            R.mipmap.clockl02_hour_0,
+            R.mipmap.clockl02_hour_1,
+            R.mipmap.clockl02_hour_2,
+            R.mipmap.clockl02_hour_3,
+            R.mipmap.clockl02_hour_4,
+            R.mipmap.clockl02_hour_5,
+            R.mipmap.clockl02_hour_6,
+            R.mipmap.clockl02_hour_7,
+            R.mipmap.clockl02_hour_8,
+            R.mipmap.clockl02_hour_9
+    };
+
+    public static int[] l02TimeMinutesImage = new int[]{
+            R.mipmap.clockl02_minutes_0,
+            R.mipmap.clockl02_minutes_1,
+            R.mipmap.clockl02_minutes_2,
+            R.mipmap.clockl02_minutes_3,
+            R.mipmap.clockl02_minutes_4,
+            R.mipmap.clockl02_minutes_5,
+            R.mipmap.clockl02_minutes_6,
+            R.mipmap.clockl02_minutes_7,
+            R.mipmap.clockl02_minutes_8,
+            R.mipmap.clockl02_minutes_9
+    };
+}
diff --git a/app/src/main/java/com/ic/launcher/entity/AppInfoEntity.java b/app/src/main/java/com/ic/launcher/entity/AppInfoEntity.java
new file mode 100644 (file)
index 0000000..394197a
--- /dev/null
@@ -0,0 +1,64 @@
+package com.ic.launcher.entity;
+
+public class AppInfoEntity {
+    private int bgColor;
+    private int appIconResId;
+    private int appTitleResId;
+    private String packageName;
+    private String activityName;
+
+    public AppInfoEntity() {
+        this.appIconResId = 0;
+        this.appTitleResId = 0;
+        this.packageName = null;
+        this.activityName = null;
+    }
+
+    public AppInfoEntity(int bgColor,int resid, int titleResId, String pckName, String activityName) {
+        this.bgColor =bgColor;
+        this.appIconResId = resid;
+        this.appTitleResId = titleResId;
+        this.packageName = pckName;
+        this.activityName = activityName;
+    }
+
+    public int getAppIconResId() {
+        return appIconResId;
+    }
+
+    public void setAppIconResId(int appIconResId) {
+        this.appIconResId = appIconResId;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public String getActivityName() {
+        return activityName;
+    }
+
+    public void setActivityName(String activityName) {
+        this.activityName = activityName;
+    }
+
+    public int getBgColor() {
+        return bgColor;
+    }
+
+    public void setBgColor(int bgColor) {
+        this.bgColor = bgColor;
+    }
+
+    public int getAppTitleResId() {
+        return appTitleResId;
+    }
+
+    public void setAppTitleResId(int appTitleResId) {
+        this.appTitleResId = appTitleResId;
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/fragment/AppListFragment.java b/app/src/main/java/com/ic/launcher/fragment/AppListFragment.java
new file mode 100644 (file)
index 0000000..3bd0537
--- /dev/null
@@ -0,0 +1,155 @@
+package com.ic.launcher.fragment;
+
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.LinearSmoothScroller;
+import androidx.recyclerview.widget.PagerSnapHelper;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.IcLauncherApplication;
+import com.ic.launcher.R;
+import com.ic.launcher.adapter.AppInfoAdapter;
+import com.ic.launcher.entity.AppInfoEntity;
+import com.ic.launcher.listener.IChangeMainFragmentListener;
+import com.ic.launcher.listener.ICheckAppItemListener;
+import com.ic.launcher.mode.AppListModel;
+import com.ic.launcher.util.IcLog;
+
+import static android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
+
+
+public class AppListFragment extends Fragment {
+    private static final String TAG = "AppListFragment";
+
+    private Context mContext;
+    private RecyclerView mAppRv;
+
+    private IcLauncherApplication mApp;
+
+    private TopSmoothScroller mScroller;
+    private LinearLayoutManager mLayoutManager;
+    private IChangeMainFragmentListener changeMainFragmentListener;
+    private AppInfoAdapter appAdapter;
+
+    private AppListModel appListModel;
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        this.mContext = context;
+
+        if (context instanceof IChangeMainFragmentListener) {
+            changeMainFragmentListener = (IChangeMainFragmentListener) context;
+        } else {
+            throw new RuntimeException(context.toString()
+                    + " must implement MainClockGestureDetectorImpl.OnClockGestureFlingListener");
+        }
+    }
+
+    public static AppListFragment newInstance() {
+        return new AppListFragment();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mApp = (IcLauncherApplication) mContext.getApplicationContext();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_app_list, container, false);
+        mAppRv = view.findViewById(R.id.app_list);
+        initRecyclerView();
+        initAppListModel();
+        return view;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mScroller.setTargetPosition(0);
+        mLayoutManager.startSmoothScroll(mScroller);
+    }
+
+    private void initRecyclerView(){
+        appAdapter = new AppInfoAdapter(mContext,itemListener);
+        mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
+
+        mAppRv.setLayoutManager(mLayoutManager);
+        mAppRv.setAdapter(appAdapter);
+
+        new PagerSnapHelper().attachToRecyclerView(mAppRv);
+
+        mAppRv.addOnScrollListener(scrollListener);
+
+        mScroller = new TopSmoothScroller(mContext);
+    }
+
+    private void initAppListModel() {
+
+        AppListModel.Factory factory = new AppListModel.Factory(mApp,mApp.getAppListPresenter());
+        appListModel = new ViewModelProvider(this, factory).get(AppListModel.class);
+
+        appListModel.getObsAppInfoList().observe(getViewLifecycleOwner(), appList -> {
+            appAdapter.updateAppInfoList(appList);
+        });
+
+        appListModel.updateAppInfoList();
+    }
+
+    private RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
+
+        private boolean isAllowLeft = false;
+        private boolean isAllowRight = false;
+
+        @Override
+        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+            super.onScrollStateChanged(recyclerView, newState);
+            if (newState == SCROLL_STATE_IDLE) {
+                if (!isAllowLeft || !isAllowRight) {
+                    //此处返回主界面
+                    IcLog.i(TAG, "Change To Main Fragment");
+                    changeMainFragmentListener.onChangeMain();
+                }
+            }
+        }
+
+        @Override
+        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+            super.onScrolled(recyclerView, dx, dy);
+            isAllowLeft = mAppRv.canScrollHorizontally(-1);
+            isAllowRight = mAppRv.canScrollHorizontally(1);
+        }
+    };
+
+    private class TopSmoothScroller extends LinearSmoothScroller{
+        public TopSmoothScroller(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected int getHorizontalSnapPreference() {
+            return SNAP_TO_START;//具体见源码注释
+        }
+    }
+
+    private ICheckAppItemListener itemListener = new ICheckAppItemListener() {
+        @Override
+        public void onAppItem(int pos) {
+            appListModel.onStartAppActivity(pos);
+        }
+    };
+}
diff --git a/app/src/main/java/com/ic/launcher/fragment/L02MainFragment.java b/app/src/main/java/com/ic/launcher/fragment/L02MainFragment.java
new file mode 100644 (file)
index 0000000..8027c59
--- /dev/null
@@ -0,0 +1,107 @@
+package com.ic.launcher.fragment;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.core.view.GestureDetectorCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.R;
+import com.ic.launcher.fragment.l02.L02WatchFragment;
+import com.ic.launcher.fragment.l02.L02StatusBarFragment;
+import com.ic.launcher.listener.MainClockGestureDetectorImpl;
+
+
+public class L02MainFragment extends Fragment {
+
+    private Context mContext;
+
+    private L02StatusBarFragment statusBarFt;
+    private L02WatchFragment watchFt;
+
+    private GestureDetectorCompat gesture;
+
+    private MainClockGestureDetectorImpl.OnClockGestureFlingListener flingListener;
+
+    public static L02MainFragment newInstance() {
+        return new L02MainFragment();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_l02_main, container, false);
+        statusBarFt = (L02StatusBarFragment) getChildFragmentManager().findFragmentById(R.id.l02_status_fl);
+        watchFt = (L02WatchFragment) getChildFragmentManager().findFragmentById(R.id.l02_watch_fl);
+        //监听事件
+        initOnTouchListener(view);
+        return view;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        controlStatusBar(true);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        controlStatusBar(false);
+    }
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        this.mContext = context;
+        if (context instanceof MainClockGestureDetectorImpl.OnClockGestureFlingListener) {
+            flingListener = (MainClockGestureDetectorImpl.OnClockGestureFlingListener) context;
+        } else {
+            throw new RuntimeException(context.toString()
+                    + " must implement MainClockGestureDetectorImpl.OnClockGestureFlingListener");
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+    }
+
+
+    /**
+     * 状态显示与隐藏
+     *
+     * @param isShow true 显示  false 隐藏  在 onResume 与 onPause 控制
+     */
+    private void controlStatusBar(boolean isShow) {
+        FragmentTransaction ft = getChildFragmentManager().beginTransaction();
+        if (isShow && !statusBarFt.isVisible()) {
+            ft.show(statusBarFt).commit();
+        } else {
+            ft.hide(statusBarFt).commit();
+        }
+    }
+
+    @SuppressLint("ClickableViewAccessibility")
+    private void initOnTouchListener(View view) {
+        gesture = new GestureDetectorCompat(mContext,new MainClockGestureDetectorImpl(flingListener));
+        view.setOnTouchListener((v, event) -> {
+            if (gesture.onTouchEvent(event)) {
+                return true;
+            }
+            return true;
+        });
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/fragment/l02/L02StatusBarFragment.java b/app/src/main/java/com/ic/launcher/fragment/l02/L02StatusBarFragment.java
new file mode 100644 (file)
index 0000000..bda1c9c
--- /dev/null
@@ -0,0 +1,97 @@
+package com.ic.launcher.fragment.l02;
+
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.IcLauncherApplication;
+import com.ic.launcher.databinding.FragmentL02StatusBarBinding;
+import com.ic.launcher.mode.StateBarModel;
+
+
+public class L02StatusBarFragment extends Fragment {
+    private static final String TAG = "L02StatusBarFt";
+
+    private Context mContext;
+    private IcLauncherApplication mApp;
+    private FragmentL02StatusBarBinding mStateBarBinding;
+
+    private StateBarModel phoneModel;
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        mContext = context;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mApp = (IcLauncherApplication) mContext.getApplicationContext();
+    }
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        mStateBarBinding = FragmentL02StatusBarBinding.inflate(inflater, container, false);
+        initStateBarModel();
+        return mStateBarBinding.getRoot();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        phoneModel.onResumeView();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        phoneModel.onPauseView();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        phoneModel.onDestroyView();
+    }
+
+    private void initStateBarModel() {
+
+        StateBarModel.Factory factory = new StateBarModel.Factory(mApp, mApp.getPhoneStatePresenter(), mApp.getBatterPresenter());
+        phoneModel = new ViewModelProvider(this, factory).get(StateBarModel.class);
+        phoneModel.getObsPhoneSignalID().observe(getViewLifecycleOwner(), resID -> {
+            mStateBarBinding.setPhoneSignal(resID);
+        });
+
+        phoneModel.getObsPhoneTransportID().observe(getViewLifecycleOwner(), resID -> {
+            mStateBarBinding.setPhoneTransport(resID);
+        });
+
+        phoneModel.getObsPhoneTypeID().observe(getViewLifecycleOwner(), resID -> {
+            mStateBarBinding.setPhoneNetType(resID);
+        });
+
+        phoneModel.getObsBatteryCharging().observe(getViewLifecycleOwner(), charging -> {
+            mStateBarBinding.setBatteryCharge(charging);
+        });
+
+        phoneModel.getObsBatteryResID().observe(getViewLifecycleOwner(),resID ->{
+            mStateBarBinding.setBatteryDrawable(resID);
+        });
+
+        phoneModel.getObsBatteryValue().observe(getViewLifecycleOwner(),value ->{
+            mStateBarBinding.setBatteryValue(value);
+        });
+
+        phoneModel.querySimCardState();
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/fragment/l02/L02WatchFragment.java b/app/src/main/java/com/ic/launcher/fragment/l02/L02WatchFragment.java
new file mode 100644 (file)
index 0000000..0183986
--- /dev/null
@@ -0,0 +1,86 @@
+package com.ic.launcher.fragment.l02;
+
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.ic.launcher.IcLauncherApplication;
+import com.ic.launcher.databinding.FragmentL02WatchBinding;
+import com.ic.launcher.mode.WatchFaceModel;
+
+public class L02WatchFragment extends Fragment {
+
+    private Context mContext;
+    private IcLauncherApplication mApp;
+
+    private WatchFaceModel watchFaceModel;
+
+    private FragmentL02WatchBinding watchBinding;
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        mContext = context;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mApp = (IcLauncherApplication) mContext.getApplicationContext();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+
+        watchBinding = FragmentL02WatchBinding.inflate(inflater, container, false);
+        initWatchFaceModel();
+
+        watchBinding.setHeartValue("100");
+        watchBinding.setStepValue("100000");
+        return watchBinding.getRoot();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        watchFaceModel.onResumeView();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        watchFaceModel.onPauseView();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        watchFaceModel.onDestroyView();
+    }
+
+    private void initWatchFaceModel() {
+        WatchFaceModel.Factory factory = new WatchFaceModel.Factory(mApp, mApp.getTimeDatePresenter());
+        watchFaceModel = new ViewModelProvider(this, factory).get(WatchFaceModel.class);
+
+        watchFaceModel.getObsTime().observe(getViewLifecycleOwner(), timeList -> {
+            watchBinding.setTimeText(timeList);
+        });
+
+        watchFaceModel.getObsWeek().observe(getViewLifecycleOwner(), week -> {
+            watchBinding.setWatchWeek(week);
+        });
+
+        watchFaceModel.getObsYear().observe(getViewLifecycleOwner(), year -> {
+            watchBinding.setWatchDate(year);
+        });
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/listener/IChangeMainFragmentListener.java b/app/src/main/java/com/ic/launcher/listener/IChangeMainFragmentListener.java
new file mode 100644 (file)
index 0000000..3622e12
--- /dev/null
@@ -0,0 +1,5 @@
+package com.ic.launcher.listener;
+
+public interface IChangeMainFragmentListener {
+    void onChangeMain();
+}
diff --git a/app/src/main/java/com/ic/launcher/listener/ICheckAppItemListener.java b/app/src/main/java/com/ic/launcher/listener/ICheckAppItemListener.java
new file mode 100644 (file)
index 0000000..a75a899
--- /dev/null
@@ -0,0 +1,5 @@
+package com.ic.launcher.listener;
+
+public interface ICheckAppItemListener {
+    void onAppItem(int pos);
+}
diff --git a/app/src/main/java/com/ic/launcher/listener/MainClockGestureDetectorImpl.java b/app/src/main/java/com/ic/launcher/listener/MainClockGestureDetectorImpl.java
new file mode 100644 (file)
index 0000000..dab2a74
--- /dev/null
@@ -0,0 +1,43 @@
+package com.ic.launcher.listener;
+
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+import com.ic.launcher.util.IcLog;
+
+public class MainClockGestureDetectorImpl extends GestureDetector.SimpleOnGestureListener {
+    private static final String TAG = "MainClockGesture";
+
+    public interface OnClockGestureFlingListener{
+        void onDirection(int flag);
+    }
+
+    private OnClockGestureFlingListener mListener;
+
+    public MainClockGestureDetectorImpl(OnClockGestureFlingListener flingListener ){
+        this.mListener = flingListener;
+    }
+
+    @Override
+    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+        IcLog.i(TAG, "onFling x1:" + e1.getX()+ "x2:" + e2.getX());
+
+        if(e1.getX() - e2.getX() > 30){
+            onCallBackListener(1);
+            return true;
+        }
+
+        if(e2.getX() - e1.getX() > 30){
+            onCallBackListener(2);
+            return true;
+        }
+
+        return super.onFling(e1, e2, velocityX, velocityY);
+    }
+
+    private void onCallBackListener(int flag){
+        if(mListener != null){
+            mListener.onDirection(flag);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/mode/AppListModel.java b/app/src/main/java/com/ic/launcher/mode/AppListModel.java
new file mode 100644 (file)
index 0000000..549e742
--- /dev/null
@@ -0,0 +1,65 @@
+package com.ic.launcher.mode;
+
+import android.app.Application;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.ic.launcher.entity.AppInfoEntity;
+import com.ic.launcher.presenter.AppListPresenter;
+
+import java.util.List;
+
+
+public class AppListModel extends AndroidViewModel {
+
+    private final AppListPresenter appListPresenter;
+
+    private final LiveData<List<AppInfoEntity>> mObsAppInfoList;
+
+    public AppListModel(@NonNull Application application,
+                        @NonNull AppListPresenter appListPresenter) {
+        super(application);
+        this.appListPresenter = appListPresenter;
+        mObsAppInfoList = appListPresenter.getObsAppInfoList();
+    }
+
+    public LiveData<List<AppInfoEntity>> getObsAppInfoList() {
+        return mObsAppInfoList;
+    }
+
+    public void updateAppInfoList() {
+        appListPresenter.updateSystemApp();
+    }
+
+    public void onStartAppActivity(int pos) {
+        appListPresenter.startAppActivity(pos);
+    }
+
+    public static class Factory extends ViewModelProvider.NewInstanceFactory {
+
+        @NonNull
+        private final Application mApplication;
+
+        @NonNull
+        private final AppListPresenter appListPresenter;
+
+
+        public Factory(@NonNull Application application,
+                       @NonNull AppListPresenter appListPresenter) {
+            mApplication = application;
+            this.appListPresenter = appListPresenter;
+
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        @NonNull
+        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+            return (T) new AppListModel(mApplication, appListPresenter);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/mode/StateBarModel.java b/app/src/main/java/com/ic/launcher/mode/StateBarModel.java
new file mode 100644 (file)
index 0000000..6c02a44
--- /dev/null
@@ -0,0 +1,113 @@
+package com.ic.launcher.mode;
+
+import android.app.Application;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.ic.launcher.presenter.BatteryPresenter;
+import com.ic.launcher.presenter.PhoneStatePresenter;
+
+public class StateBarModel extends AndroidViewModel {
+
+    private final LiveData<Integer> mObsPhoneTypeID;
+    private final LiveData<Integer> mObsPhoneSignalID;
+    private final LiveData<Integer> mObsPhoneTransportID;
+
+    private final LiveData<String> mObsBatteryValue;
+    private final LiveData<Boolean> mObsBatteryCharging;
+    private final LiveData<Integer> mObsBatteryResID;
+
+    private PhoneStatePresenter mPhonePresenter;
+    private BatteryPresenter mBatteryPresenter;
+
+    public StateBarModel(@NonNull Application application,
+                         @NonNull PhoneStatePresenter phonePresenter,
+                         @NonNull BatteryPresenter batteryPresenter) {
+        super(application);
+        mPhonePresenter = phonePresenter;
+        mBatteryPresenter = batteryPresenter;
+
+        mObsPhoneSignalID = mPhonePresenter.getPhoneSignalObservable();
+        mObsPhoneTypeID = mPhonePresenter.getPhoneTypeObservable();
+        mObsPhoneTransportID = mPhonePresenter.getPhoneTransportObservable();
+
+        mObsBatteryCharging = mBatteryPresenter.getObsBatteryCharging();
+        mObsBatteryResID = mBatteryPresenter.getObsBatteryResID();
+        mObsBatteryValue = mBatteryPresenter.getObsBatteryValue();
+    }
+
+    public LiveData<Integer> getObsPhoneTypeID() {
+        return mObsPhoneTypeID;
+    }
+
+    public LiveData<Integer> getObsPhoneSignalID() {
+        return mObsPhoneSignalID;
+    }
+
+    public LiveData<Integer> getObsPhoneTransportID() {
+        return mObsPhoneTransportID;
+    }
+
+    public LiveData<String> getObsBatteryValue() {
+        return mObsBatteryValue;
+    }
+
+    public LiveData<Boolean> getObsBatteryCharging() {
+        return mObsBatteryCharging;
+    }
+
+    public LiveData<Integer> getObsBatteryResID() {
+        return mObsBatteryResID;
+    }
+
+    public void querySimCardState(){
+        mPhonePresenter.querySimCardState();
+    }
+
+    public void onResumeView(){
+        mPhonePresenter.onResumePresenter();
+        mBatteryPresenter.registerBatteryReceiver();
+    }
+
+    public void onPauseView(){
+        mPhonePresenter.onPausePresenter();
+        mBatteryPresenter.unRegisterBatteryReceiver();
+    }
+
+    public void onDestroyView(){
+        mPhonePresenter.onDestroyPresenter();
+    }
+
+    public static class Factory extends ViewModelProvider.NewInstanceFactory {
+
+        @NonNull
+        private final Application mApplication;
+
+        @NonNull
+        private final PhoneStatePresenter phonePresenter;
+
+        @NonNull
+        private final BatteryPresenter batteryPresenter;
+
+        public Factory(@NonNull Application application,
+                       @NonNull PhoneStatePresenter phonePresenter,
+                       @NonNull BatteryPresenter batteryPresenter) {
+            mApplication = application;
+            this.phonePresenter = phonePresenter;
+            this.batteryPresenter = batteryPresenter;
+
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        @NonNull
+        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+            return (T) new StateBarModel(mApplication, phonePresenter,batteryPresenter);
+        }
+    }
+
+}
diff --git a/app/src/main/java/com/ic/launcher/mode/WatchFaceModel.java b/app/src/main/java/com/ic/launcher/mode/WatchFaceModel.java
new file mode 100644 (file)
index 0000000..dff03e4
--- /dev/null
@@ -0,0 +1,82 @@
+package com.ic.launcher.mode;
+
+import android.app.Application;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MediatorLiveData;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.ic.launcher.presenter.TimeDatePresenter;
+
+import java.util.ArrayList;
+
+
+public class WatchFaceModel extends AndroidViewModel {
+
+    private TimeDatePresenter timeDatePresenter;
+
+    private final LiveData<ArrayList<Integer>> mObsTime;
+    private final LiveData<String> mObsYear;
+    private final LiveData<String> mObsWeek;
+
+
+    public WatchFaceModel(@NonNull Application application,
+                          @NonNull TimeDatePresenter timeDatePresenter) {
+        super(application);
+        this.timeDatePresenter = timeDatePresenter;
+        mObsTime = timeDatePresenter.getObsTime();
+        mObsYear = timeDatePresenter.getObsYear();
+        mObsWeek = timeDatePresenter.getmObsWeek();
+    }
+
+    public LiveData<ArrayList<Integer>> getObsTime() {
+        return mObsTime;
+    }
+
+    public LiveData<String> getObsYear() {
+        return mObsYear;
+    }
+
+    public LiveData<String> getObsWeek() {
+        return mObsWeek;
+    }
+
+    public void onResumeView() {
+        timeDatePresenter.onResumePresenter();
+    }
+
+    public void onPauseView() {
+        timeDatePresenter.onPausePresenter();
+    }
+
+    public void onDestroyView() {
+        timeDatePresenter.unRegisterTimeDateReceiver();
+    }
+
+    public static class Factory extends ViewModelProvider.NewInstanceFactory {
+
+        @NonNull
+        private final Application mApplication;
+
+        @NonNull
+        private final TimeDatePresenter timeDatePresenter;
+
+
+        public Factory(@NonNull Application application,
+                       @NonNull TimeDatePresenter timeDatePresenter) {
+            mApplication = application;
+            this.timeDatePresenter = timeDatePresenter;
+
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        @NonNull
+        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+            return (T) new WatchFaceModel(mApplication, timeDatePresenter);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/presenter/AppListPresenter.java b/app/src/main/java/com/ic/launcher/presenter/AppListPresenter.java
new file mode 100644 (file)
index 0000000..e07f88f
--- /dev/null
@@ -0,0 +1,68 @@
+package com.ic.launcher.presenter;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import androidx.lifecycle.MutableLiveData;
+
+import com.ic.launcher.R;
+import com.ic.launcher.configure.l02.L02AppInfo;
+import com.ic.launcher.entity.AppInfoEntity;
+
+import java.util.List;
+
+public class AppListPresenter {
+
+    private Context context;
+    private MutableLiveData<List<AppInfoEntity>> mObsAppInfoList;
+    private MutableLiveData<String> mObsActivityError;
+
+    private String mErrorInfo;
+
+    public AppListPresenter(Context context){
+        this.context=context;
+        mObsAppInfoList = new MutableLiveData<>();
+        mObsActivityError = new MutableLiveData<>();
+
+        mErrorInfo  = context.getString(R.string.error_start_activity);
+    }
+
+    public MutableLiveData<List<AppInfoEntity>> getObsAppInfoList() {
+        return mObsAppInfoList;
+    }
+
+    public MutableLiveData<String> getObsActivityError() {
+        return mObsActivityError;
+    }
+
+    public void updateSystemApp(){
+        mObsAppInfoList.setValue(L02AppInfo.mL02DefaultAppList);
+    }
+
+    public void startAppActivity(int index){
+        if(index <0 || index > L02AppInfo.mL02DefaultAppList.size()){
+            mObsActivityError.setValue(mErrorInfo);
+            return;
+        }
+
+        AppInfoEntity entity = L02AppInfo.mL02DefaultAppList.get(index);
+        String pck = entity.getPackageName();
+        String activity = entity.getActivityName();
+
+        if(TextUtils.isEmpty(pck) || TextUtils.isEmpty(activity)){
+            mObsActivityError.setValue(mErrorInfo);
+            return;
+        }
+
+        try {
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setComponent(new ComponentName(pck, activity));
+            context.startActivity(intent);
+        } catch (Exception e ) {
+            mObsActivityError.setValue(mErrorInfo);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/presenter/BatteryPresenter.java b/app/src/main/java/com/ic/launcher/presenter/BatteryPresenter.java
new file mode 100644 (file)
index 0000000..53f0f84
--- /dev/null
@@ -0,0 +1,107 @@
+package com.ic.launcher.presenter;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.text.TextUtils;
+
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.configure.l02.L02Icon;
+
+public class BatteryPresenter {
+
+    private Context mContext;
+
+    private MediatorLiveData<String> mObsBatteryValue;
+    private MediatorLiveData<Boolean> mObsBatteryCharging;
+    private MediatorLiveData<Integer> mObsBatteryResID;
+
+    public MediatorLiveData<String> getObsBatteryValue() {
+        return mObsBatteryValue;
+    }
+
+    public MediatorLiveData<Boolean> getObsBatteryCharging() {
+        return mObsBatteryCharging;
+    }
+
+    public MediatorLiveData<Integer> getObsBatteryResID() {
+        return mObsBatteryResID;
+    }
+
+    public BatteryPresenter(Context context) {
+        mContext = context;
+
+        mObsBatteryValue = new MediatorLiveData<>();
+        mObsBatteryCharging = new MediatorLiveData<>();
+        mObsBatteryResID = new MediatorLiveData<>();
+    }
+
+    public void registerBatteryReceiver() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        mContext.registerReceiver(mIntentReceiver, filter);
+    }
+
+    public void unRegisterBatteryReceiver() {
+        mContext.unregisterReceiver(mIntentReceiver);
+    }
+
+    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent != null) {
+                String acyion = intent.getAction();
+
+                if (TextUtils.isEmpty(acyion)) {
+                    return;
+                }
+
+                if (Intent.ACTION_BATTERY_CHANGED.equals(acyion)) {
+                    int status = intent.getIntExtra("status", -1);
+                    int rawlevel = intent.getIntExtra("level", -1);
+                    int scale = intent.getIntExtra("scale", -1);
+                    updateBatteryValue(rawlevel, scale);
+                    updateBatteryCharging(status);
+                }
+            }
+        }
+    };
+
+    private void updateBatteryValue(int rawlevel, int scale) {
+        int level = -1; // percentage, or -1 for unknown
+        if (rawlevel >= 0 && scale > 0) {
+            level = (rawlevel * 100) / scale;
+        }
+        mObsBatteryResID.setValue(L02Icon.l02BatteryResId[getBatteryLevel(level)]);
+        mObsBatteryValue.setValue(level + "%");
+    }
+
+    private void updateBatteryCharging(int state) {
+        if (BatteryManager.BATTERY_STATUS_CHARGING == state) {
+            mObsBatteryCharging.setValue(true);
+        }else {
+            mObsBatteryCharging.setValue(false);
+        }
+    }
+
+    private int getBatteryLevel(int level) {
+        int index = 0;
+        if (level > 85) {
+            index = 5;
+        } else if (level > 65) {
+            index = 4;
+        } else if (level > 40) {
+            index = 3;
+        } else if (level > 15) {
+            index = 2;
+        } else if (level > 7) {
+            index = 1;
+        }
+
+        return index;
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/presenter/PhoneStatePresenter.java b/app/src/main/java/com/ic/launcher/presenter/PhoneStatePresenter.java
new file mode 100644 (file)
index 0000000..52293bc
--- /dev/null
@@ -0,0 +1,171 @@
+package com.ic.launcher.presenter;
+
+import android.content.Context;
+import android.telephony.PhoneStateListener;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.util.IcLog;
+
+
+import static com.ic.launcher.configure.l02.L02Icon.l02PhoneTypeResId;
+import static com.ic.launcher.configure.l02.L02Icon.l02SignalResId;
+
+public class PhoneStatePresenter {
+    private static final String TAG = "PhoneStatePresenter";
+
+    private MediatorLiveData<Integer> mObsPhoneTypeID;
+    private MediatorLiveData<Integer> mObsPhoneSignalID;
+    private MediatorLiveData<Integer> mObsPhoneTransportID;
+
+    private QueryTrafficPooler trafficPooler;
+
+    private TelephonyManager mTM;
+
+    private Thread mThread;
+
+    private boolean isSimCard = false;
+
+    public PhoneStatePresenter(Context context) {
+        mTM = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        mObsPhoneTypeID = new MediatorLiveData<>();
+        mObsPhoneSignalID = new MediatorLiveData<>();
+        mObsPhoneTransportID = new MediatorLiveData<>();
+
+        trafficPooler = new QueryTrafficPooler(mObsPhoneTransportID);
+    }
+
+    public LiveData<Integer> getPhoneTypeObservable() {
+        return mObsPhoneTypeID;
+    }
+
+    public LiveData<Integer> getPhoneSignalObservable() {
+        return mObsPhoneSignalID;
+    }
+
+    public LiveData<Integer> getPhoneTransportObservable() {
+        return mObsPhoneTransportID;
+    }
+
+    public void querySimCardState() {
+        int resIdIndex = 0;
+        if (mTM == null) {
+            return;
+        }
+
+        int simState = mTM.getSimState();
+        switch (simState) {
+            case TelephonyManager.SIM_STATE_READY:
+                resIdIndex = 2;
+                break;
+            case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
+            case TelephonyManager.SIM_STATE_PUK_REQUIRED:
+            case TelephonyManager.SIM_STATE_PIN_REQUIRED:
+                resIdIndex = 1;
+                break;
+        }
+
+        if (resIdIndex == 2) {
+            mObsPhoneTypeID.setValue(queryPhoneNetworkTypeResId(mTM));
+            mObsPhoneSignalID.setValue(l02SignalResId[6]);
+            startQueryTraffic();
+            isSimCard = true;
+        } else if (resIdIndex == 1) {
+            mObsPhoneSignalID.setValue(l02SignalResId[1]);
+        } else {
+            mObsPhoneSignalID.setValue(l02SignalResId[0]);
+        }
+    }
+
+    public void onResumePresenter() {
+        if (isSimCard) {
+            resumeQueryTraffic();
+            listenPhoneState();
+        }
+    }
+
+    public void onPausePresenter() {
+        pauseQueryTraffic();
+        stopListenPhoneState();
+    }
+
+    public void onDestroyPresenter() {
+        stopQueryTraffic();
+        mTM=null;
+    }
+
+    private void startQueryTraffic() {
+        mThread = new Thread(trafficPooler);
+        mThread.start();
+    }
+
+    private void stopQueryTraffic() {
+        if (mThread != null) {
+            mThread.interrupt();
+        }
+
+        mThread = null;
+    }
+
+    public void resumeQueryTraffic() {
+        if (mThread != null && trafficPooler != null) {
+            trafficPooler.resumeQueryThread();
+        }
+    }
+
+    public void pauseQueryTraffic() {
+        if (mThread != null && trafficPooler != null) {
+            trafficPooler.pauseQueryThread();
+        }
+    }
+
+    private void listenPhoneState() {
+        if (mTM != null) {
+            mTM.listen(mPhoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+        }
+    }
+
+    private void stopListenPhoneState() {
+        if (mTM != null) {
+            mTM.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE);
+        }
+    }
+
+    private PhoneStateListener mPhoneListener = new PhoneStateListener() {
+        private int lastSignal = 0;
+
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            String ssignal = signalStrength.toString();
+            String[] parts = ssignal.split(" ");
+            lastSignal = Integer.parseInt(parts[8])-140;
+            IcLog.i(TAG, "Signal:" + lastSignal);
+            mObsPhoneSignalID.postValue(l02SignalResId[checkSignalLevel(lastSignal)]);
+            super.onSignalStrengthsChanged(signalStrength);
+        }
+    };
+
+    private int queryPhoneNetworkTypeResId(TelephonyManager tm) {
+        if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
+            return l02PhoneTypeResId[0];
+        }
+        return -1;
+    }
+
+    private int checkSignalLevel(int dbm){
+        int index=6;
+        if(dbm <= -120){
+            index=2;
+        }else if(dbm <= -111){
+            index =3;
+        }else if(dbm <= -106){
+            index =4;
+        }else if(dbm <= -91){
+            index=5;
+        }
+        return index;
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/presenter/QueryThread.java b/app/src/main/java/com/ic/launcher/presenter/QueryThread.java
new file mode 100644 (file)
index 0000000..922dd9b
--- /dev/null
@@ -0,0 +1,54 @@
+package com.ic.launcher.presenter;
+
+import com.ic.launcher.util.IcLog;
+
+public abstract class QueryThread extends Thread {
+    private static final String TAG="QueryThread";
+
+    private final Object lock = new Object();
+    private boolean pause = false;
+
+    abstract void onThreadExecute();
+
+    protected void pauseQueryThread() {
+        pause = true;
+    }
+
+    protected void resumeQueryThread() {
+        pause = false;
+        synchronized (lock) {
+            lock.notifyAll();
+        }
+    }
+
+    private void onPause() {
+        synchronized (lock) {
+            try {
+                IcLog.i(TAG, "Pause Query Phone");
+                lock.wait();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    public void run() {
+        super.run();
+        while (true) {
+            while (pause) {
+                onPause();
+            }
+
+            onThreadExecute();
+
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                //捕获到异常之后,执行break跳出循环
+                IcLog.i(TAG, "Stop Query Phone State");
+                break;
+            }
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/presenter/QueryTrafficPooler.java b/app/src/main/java/com/ic/launcher/presenter/QueryTrafficPooler.java
new file mode 100644 (file)
index 0000000..0eda9b0
--- /dev/null
@@ -0,0 +1,48 @@
+package com.ic.launcher.presenter;
+
+import android.net.TrafficStats;
+
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.util.IcLog;
+
+import static com.ic.launcher.configure.l02.L02Icon.l02TransportResId;
+
+public class QueryTrafficPooler extends QueryThread {
+
+    private static final String TAG = "QueryTrafficPooler";
+
+    private long receivedWork;
+    private long sendNetWork;
+
+    private MediatorLiveData<Integer> mObsPhoneTransportID;
+
+    public QueryTrafficPooler(MediatorLiveData<Integer> transportID) {
+        mObsPhoneTransportID = transportID;
+    }
+
+    @Override
+    void onThreadExecute() {
+        getTrafficPollerValue();
+    }
+
+    private void getTrafficPollerValue() {
+        long rw = TrafficStats.getMobileRxPackets();
+        long sw = TrafficStats.getMobileTxPackets();
+        int index = 0;
+        if (rw > receivedWork && sw > sendNetWork) {
+            index = 3;
+        } else {
+            if (rw > receivedWork) {
+                index = 1;
+            }
+            if (sw > sendNetWork) {
+                index = 2;
+            }
+        }
+        IcLog.i(TAG, "receivedWork:" + receivedWork + "sendNetWork:" + sendNetWork);
+        receivedWork = rw;
+        sendNetWork = sw;
+        mObsPhoneTransportID.postValue(l02TransportResId[index]);
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/presenter/TimeDatePresenter.java b/app/src/main/java/com/ic/launcher/presenter/TimeDatePresenter.java
new file mode 100644 (file)
index 0000000..be1e7ac
--- /dev/null
@@ -0,0 +1,135 @@
+package com.ic.launcher.presenter;
+
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.text.format.DateFormat;
+
+import androidx.lifecycle.MediatorLiveData;
+
+import com.ic.launcher.util.IcLog;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import static com.ic.launcher.configure.l02.L02Icon.l02TimeHourImage;
+import static com.ic.launcher.configure.l02.L02Icon.l02TimeMinutesImage;
+public class TimeDatePresenter {
+
+    private static final String TAG = "TimeDatePresenter";
+
+    private static final CharSequence DEFAULT_FORMAT_24_HOUR = "HH:mm";
+    private static final CharSequence DEFAULT_FORMAT_MM_DD = "MM-dd";
+    private static final CharSequence DEFAULT_FORMAT_EEEEE = "EEEE";
+
+    private MediatorLiveData<ArrayList<Integer>> mObsTime;
+    private MediatorLiveData<String> mObsYear;
+    private MediatorLiveData<String> mObsWeek;
+
+
+    private Context mContext;
+    private Calendar mTime;
+    private boolean mShouldRunTicker = false;
+
+    private ArrayList<Integer> timeList;
+
+    public TimeDatePresenter(Context context) {
+        mContext = context;
+        timeList = new ArrayList<>();
+        registerTimeDateReceiver();
+        createTime(null);
+
+        mObsTime = new MediatorLiveData<>();
+        mObsYear = new MediatorLiveData<>();
+        mObsWeek = new MediatorLiveData<>();
+    }
+
+    public MediatorLiveData<ArrayList<Integer>> getObsTime() {
+        return mObsTime;
+    }
+
+    public MediatorLiveData<String> getObsYear() {
+        return mObsYear;
+    }
+
+    public MediatorLiveData<String> getmObsWeek() {
+        return mObsWeek;
+    }
+
+    public void onResumePresenter() {
+        onTimeChanged();
+        mShouldRunTicker = true;
+    }
+
+    public void onPausePresenter() {
+        mShouldRunTicker = false;
+    }
+
+    public void registerTimeDateReceiver() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_TIME_TICK);
+        filter.addAction(Intent.ACTION_TIME_CHANGED);
+        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+        mContext.registerReceiver(mIntentReceiver, filter);
+    }
+
+    public void unRegisterTimeDateReceiver() {
+        mContext.unregisterReceiver(mIntentReceiver);
+    }
+
+    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+                final String timeZone = intent.getStringExtra("time-zone");
+                createTime(timeZone);
+            } else if (!mShouldRunTicker && (Intent.ACTION_TIME_TICK.equals(intent.getAction())
+                    || Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))) {
+                return;
+            }
+            onTimeChanged();
+        }
+    };
+
+    private void createTime(String timeZone) {
+        if (timeZone != null) {
+            mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
+        } else {
+            mTime = Calendar.getInstance();
+        }
+    }
+
+    private void onTimeChanged() {
+        mTime.setTimeInMillis(System.currentTimeMillis());
+
+        CharSequence time = DateFormat.format(DEFAULT_FORMAT_24_HOUR, mTime);
+        CharSequence mmdd = DateFormat.format(DEFAULT_FORMAT_MM_DD, mTime);
+        CharSequence week = DateFormat.format(DEFAULT_FORMAT_EEEEE, mTime);
+
+        timeList.clear();
+
+        boolean isHour=true;
+
+        for(int i=0; i<time.length(); i++){
+            if(time.charAt(i) == ':'){
+                isHour=false;
+                continue;
+            }
+
+            if(isHour){
+                timeList.add(l02TimeHourImage[Character.getNumericValue(time.charAt(i))]);
+            }else{
+                timeList.add(l02TimeMinutesImage[Character.getNumericValue(time.charAt(i))]);
+            }
+        }
+
+        mObsTime.setValue(timeList);
+        mObsYear.setValue(mmdd.toString());
+        mObsWeek.setValue(week.toString());
+
+        IcLog.i(TAG, "time" + time.toString() + " mmdd:" + mmdd.toString() + " week" + week.toString());
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/util/IcLog.java b/app/src/main/java/com/ic/launcher/util/IcLog.java
new file mode 100644 (file)
index 0000000..0acad7c
--- /dev/null
@@ -0,0 +1,59 @@
+package com.ic.launcher.util;
+
+import android.util.Log;
+
+import com.ic.launcher.BuildConfig;
+
+/**
+ * @author RyanLee
+ * @date 2018/2/2
+ */
+
+public class IcLog {
+
+    private static final String DOT = ".";
+    private static boolean isDebug = BuildConfig.DEBUG;
+    private static String tagHead = "";
+
+    public static void v(String tag, String msg) {
+        if (isDebug) {
+            Log.v(mergeHeadTag(tag), msg);
+        }
+    }
+
+    public static void d(String tag, String msg) {
+        if (isDebug) {
+            Log.d(mergeHeadTag(tag), msg);
+        }
+    }
+
+    public static void i(String tag, String msg) {
+        if (isDebug) {
+            Log.i(mergeHeadTag(tag), msg);
+        }
+    }
+
+    public static void w(String tag, String msg) {
+        if (isDebug) {
+            Log.w(mergeHeadTag(tag), msg);
+        }
+    }
+
+    public static void e(String tag, String msg) {
+        if (isDebug) {
+            Log.e(mergeHeadTag(tag), msg);
+        }
+    }
+
+    public static void setDebug(boolean debug) {
+        isDebug = debug;
+    }
+
+    public static void setLogHead(String head) {
+        tagHead = head + DOT;
+    }
+
+    private static String mergeHeadTag(final String tag) {
+        return tagHead + tag;
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/util/OsUtil.java b/app/src/main/java/com/ic/launcher/util/OsUtil.java
new file mode 100644 (file)
index 0000000..9667d8f
--- /dev/null
@@ -0,0 +1,52 @@
+package com.ic.launcher.util;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+
+/**
+ *
+ * @author RyanLee
+ * @date 2017/11/29
+ */
+
+public class OsUtil {
+    public static int dpToPx(int dp) {
+        return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
+    }
+
+    public static int pxToDp(int px) {
+        return (int) (px / Resources.getSystem().getDisplayMetrics().density);
+    }
+
+
+    /**
+     * 获取屏幕宽度
+     *
+     * @return
+     */
+    public static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    /**
+     * 获取屏幕高度
+     *
+     * @return
+     */
+    public static int getScreenHeigth() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    /**
+     * 获取屏幕宽度
+     *
+     * @return
+     */
+    public static int getScreenWidth(Activity activity) {
+        DisplayMetrics outMetrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
+        return outMetrics.widthPixels;
+
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/util/ServiceUtil.java b/app/src/main/java/com/ic/launcher/util/ServiceUtil.java
new file mode 100644 (file)
index 0000000..c79a084
--- /dev/null
@@ -0,0 +1,42 @@
+package com.ic.launcher.util;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+
+import java.util.List;
+
+public class ServiceUtil {
+
+    public static void startServiceUtil(Context context , String serviceAction, String packageName) {
+        Intent intent = getExplicitIntent(context, new Intent(serviceAction));
+        if(intent != null){
+            intent.setPackage(packageName);
+            context.startService(intent);
+        }
+    }
+
+    public static void bindServiceUtil(Context context , String action, ServiceConnection connection,int type) {
+        Intent in = getExplicitIntent(context, new Intent(action));
+        if(in != null){
+            in.putExtra("REQ_TYPE",type);
+            context.bindService(in, connection, 0);
+        }
+    }
+
+    private static Intent getExplicitIntent(Context context, Intent impl) {
+        List<ResolveInfo> resolveInfo = context.getPackageManager().queryIntentServices(impl, 0);
+
+        if (resolveInfo.size() != 1) return null;
+
+        Intent intent = new Intent(impl);
+        ServiceInfo info = resolveInfo.get(0).serviceInfo;
+        if (info == null) return null;
+        intent.setComponent(new ComponentName(info.packageName, info.name));
+
+        return intent;
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/widget/ClockWatchView.java b/app/src/main/java/com/ic/launcher/widget/ClockWatchView.java
new file mode 100644 (file)
index 0000000..bd8e8b6
--- /dev/null
@@ -0,0 +1,135 @@
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+public class ClockWatchView extends View {
+
+    private float mRadius; //外圆半径
+
+    private int mColorLong = Color.WHITE; //长线的颜色
+    private int mColorShort = Color.WHITE; //短线的颜色
+
+    //指针末尾的长度
+    private float mPointEndLength;
+
+    private Paint mPaint;
+
+    public ClockWatchView(Context context) {
+        this(context, null);
+    }
+
+    public ClockWatchView(Context context, @Nullable AttributeSet attrs) {
+        this(context, null, 0);
+    }
+
+    public ClockWatchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        //初始化画笔
+        init();
+    }
+
+    private void init() {
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setDither(true);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.save();
+
+        //移动到中心部分
+        canvas.translate(getWidth() / 2, getHeight() / 2);
+
+        //绘制刻度
+        paintScale(canvas);
+
+        canvas.restore();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+
+        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+
+
+        if (widthMode == MeasureSpec.AT_MOST
+                || widthMode == MeasureSpec.UNSPECIFIED
+                || heightMeasureSpec == MeasureSpec.AT_MOST
+                || heightMeasureSpec == MeasureSpec.UNSPECIFIED) {
+            //宽度高度至少有一个确定的值,不能同时为wrap_content
+            return;
+        } else { //至少有一个为确定值,要获取其中的最小值
+            if (widthMode == MeasureSpec.EXACTLY) {
+                setMeasuredDimension(widthSize, heightSize);
+            }
+        }
+    }
+
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mRadius = (Math.min(w, h)) / 2;
+        mPointEndLength = mRadius / 6;
+    }
+
+    private void paintScale(Canvas canvas) {
+        //设置宽度
+        mPaint.setStrokeWidth(dpToPx(1));
+        int lineWidth = 0;
+        for (int i = 0; i < 60; i++) {
+            if (i % 5 == 0) { //整点
+                mPaint.setStrokeWidth(dpToPx(2f));
+                mPaint.setColor(mColorLong);
+                lineWidth = 8;
+                mPaint.setTextSize(spToPx(26));
+                String text = ((i / 5) == 0 ? 12 : (i / 5)) + "";
+                Rect textBound = new Rect();
+                mPaint.getTextBounds(text, 0, text.length(), textBound);
+                mPaint.setColor(Color.WHITE);
+                canvas.save();
+                if (i > 15 && i < 45) {
+                    canvas.translate(0, -mRadius + lineWidth - dpToPx(5) + (textBound.bottom - textBound.top));
+                } else if (i == 15 || i == 45) {
+                    canvas.translate(0, -mRadius + lineWidth - dpToPx(8) + (textBound.bottom - textBound.top));
+                } else {
+                    canvas.translate(0, -mRadius + lineWidth + dpToPx(2) + (textBound.bottom - textBound.top));
+                }
+                canvas.rotate(-6 * i);
+                mPaint.setStyle(Paint.Style.FILL);
+                canvas.drawText(text, -(textBound.right - textBound.left) / 2, textBound.bottom+dpToPx(6) , mPaint);
+                canvas.restore();
+            } else { //非整点
+                lineWidth = 4;
+                mPaint.setColor(mColorShort);
+                mPaint.setStrokeWidth(dpToPx(0.5f));
+            }
+            canvas.drawLine(0, -mRadius, 0, -mRadius + lineWidth, mPaint);
+            canvas.rotate(6);
+        }
+        canvas.restore();
+    }
+
+    private float dpToPx(float dp) {
+        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
+    }
+
+    private float spToPx(float sp) {
+        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/widget/WidgetBatteryStateView.java b/app/src/main/java/com/ic/launcher/widget/WidgetBatteryStateView.java
new file mode 100644 (file)
index 0000000..07d4199
--- /dev/null
@@ -0,0 +1,73 @@
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+public class WidgetBatteryStateView extends LinearLayout {
+
+    private TextView batteryTv;
+    private ImageView batteryIv;
+
+    private AnimationDrawable animationDrawable;
+
+    public WidgetBatteryStateView(Context context) {
+        this(context, null);
+    }
+
+    public WidgetBatteryStateView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public WidgetBatteryStateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        View view = View.inflate(context, R.layout.widget_battery_state_layout, this);
+        batteryTv = view.findViewById(R.id.battery_tv);
+        batteryIv = view.findViewById(R.id.battery_iv);
+    }
+
+    public void updateBatteryValue(String bv) {
+        batteryTv.setText(bv);
+
+    }
+
+    public void updateBatteryDrawable(int netType) {
+        batteryIv.setImageResource(netType);
+    }
+
+    public void updateBatteryChargeState(boolean charge) {
+        if (charge) {
+            if (animationDrawable == null) {
+                batteryIv.setImageResource(R.drawable.l02_battery_charging_anim);
+                animationDrawable = (AnimationDrawable) batteryIv.getDrawable();
+                animationDrawable.start();
+            }
+        } else {
+            if (animationDrawable != null) {
+                animationDrawable.stop();
+                animationDrawable = null;
+            }
+        }
+    }
+
+
+    @BindingAdapter(value = {"app:batteryValue", "app:batteryDrawable", "app:batteryCharge"}, requireAll = false)
+    public static void updateBatteryState(WidgetBatteryStateView view, String value, int imgRes, boolean charge) {
+        if (view != null) {
+            view.updateBatteryValue(value);
+            view.updateBatteryDrawable(imgRes);
+            view.updateBatteryChargeState(charge);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/widget/WidgetPhoneStateView.java b/app/src/main/java/com/ic/launcher/widget/WidgetPhoneStateView.java
new file mode 100644 (file)
index 0000000..f4f5fb6
--- /dev/null
@@ -0,0 +1,62 @@
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+
+public class WidgetPhoneStateView extends LinearLayout {
+
+    private ImageView signalIv;
+    private ImageView netTypeIv;
+    private ImageView transportIv;
+
+    public WidgetPhoneStateView(Context context) {
+        this(context, null);
+    }
+
+    public WidgetPhoneStateView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public WidgetPhoneStateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+
+        View view = View.inflate(context, R.layout.widget_phone_state_layout, this);
+        signalIv = view.findViewById(R.id.signal_iv);
+        netTypeIv = view.findViewById(R.id.net_type_iv);
+        transportIv = view.findViewById(R.id.transport_iv);
+    }
+
+    public void updateSinalDrawable(int signal) {
+        signalIv.setImageResource(signal);
+    }
+
+    public void updateNetTypeDrawable(int netType) {
+        netTypeIv.setImageResource(netType);
+    }
+
+    public void updateTransportDrawable(int transport) {
+        transportIv.setImageResource(transport);
+    }
+
+
+    @BindingAdapter(value = {"app:signalDrawable", "app:netTypeDrawable", "app:transportDrawable"}, requireAll = false)
+    public static void updatePhoneState(WidgetPhoneStateView view, int signal, int netType, int transport) {
+        if (view != null) {
+            view.updateSinalDrawable(signal);
+            view.updateNetTypeDrawable(netType);
+            view.updateTransportDrawable(transport);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/widget/WidgetTimeImageView.java b/app/src/main/java/com/ic/launcher/widget/WidgetTimeImageView.java
new file mode 100644 (file)
index 0000000..4a8feca
--- /dev/null
@@ -0,0 +1,69 @@
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+import java.util.ArrayList;
+
+//TextClock
+public class WidgetTimeImageView extends RelativeLayout {
+
+    private ImageView mColon;
+    private ImageView[] mImageView = new ImageView[4];
+
+    private int[] oldTimeArray = new int[4];
+    private boolean isShowColon = false;
+
+    public WidgetTimeImageView(Context context) {
+        this(context, null);
+    }
+
+    public WidgetTimeImageView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public WidgetTimeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        View view = View.inflate(context, R.layout.widget_time_image_layout, this);
+        mImageView[0] = (ImageView) view.findViewById(R.id.time_hour_ten);
+        mImageView[1] = (ImageView) view.findViewById(R.id.time_hour_bit);
+        mColon = (ImageView) view.findViewById(R.id.time_colon);
+        mImageView[2] = (ImageView) view.findViewById(R.id.time_minute_ten);
+        mImageView[3] = (ImageView) view.findViewById(R.id.time_minute_bit);
+    }
+
+    private void updateTime(ArrayList<Integer> timeRes) {
+
+        if (timeRes == null || timeRes.size() == 0 || timeRes.size() != oldTimeArray.length) {
+            return;
+        }
+
+        for (int i = 0; i < timeRes.size(); i++) {
+            if (oldTimeArray[i] != timeRes.get(i)) {
+                mImageView[i].setImageResource(timeRes.get(i));
+                oldTimeArray[i] = timeRes.get(i);
+            }
+        }
+
+        if (!isShowColon) {
+            mColon.setImageResource(R.mipmap.clockl02_time_colon);
+            isShowColon = true;
+        }
+    }
+
+    @BindingAdapter(value = {"app:timeImageResId"}, requireAll = false)
+    public static void updateTimeImge(WidgetTimeImageView view, ArrayList<Integer> timeRes) {
+        if (view != null) {
+            view.updateTime(timeRes);
+        }
+    }
+}
diff --git a/app/src/main/java/com/ic/launcher/widget/WidgetTimeTextView.java b/app/src/main/java/com/ic/launcher/widget/WidgetTimeTextView.java
new file mode 100644 (file)
index 0000000..18bc38d
--- /dev/null
@@ -0,0 +1,71 @@
+package com.ic.launcher.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.databinding.BindingAdapter;
+
+import com.ic.launcher.R;
+
+import java.util.ArrayList;
+
+public class WidgetTimeTextView extends RelativeLayout {
+
+    private ImageView mColon;
+    private TextView[] mImageView = new TextView[4];
+
+    private int[] oldTimeArray = new int[]{-1,-1,-1,-1};
+    private boolean isShowColon = false;
+
+    public WidgetTimeTextView(Context context) {
+        this(context, null);
+    }
+
+    public WidgetTimeTextView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public WidgetTimeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        View view = View.inflate(context, R.layout.widget_time_text_layout, this);
+        mImageView[0] = (TextView) view.findViewById(R.id.time_hour_ten_tv);
+        mImageView[1] = (TextView) view.findViewById(R.id.time_hour_bit_tv);
+        mColon = (ImageView) view.findViewById(R.id.time_colon_tv);
+        mImageView[2] = (TextView) view.findViewById(R.id.time_minute_ten_tv);
+        mImageView[3] = (TextView) view.findViewById(R.id.time_minute_bit_tv);
+    }
+
+    private void updateTextTime(ArrayList<Integer> value) {
+        if (value == null || value.size() == 0 || value.size() != oldTimeArray.length) {
+            return;
+        }
+
+        for (int i = 0; i < value.size(); i++) {
+            if (oldTimeArray[i] != value.get(i)) {
+                if(i ==0 && value.get(i) ==0){
+                    continue;
+               }
+                mImageView[i].setText(String.valueOf(value.get(i)));
+                oldTimeArray[i] = value.get(i);
+            }
+        }
+
+        if (!isShowColon) {
+            mColon.setImageResource(R.mipmap.clockl02_time_colon);
+            isShowColon = true;
+        }
+    }
+
+    @BindingAdapter(value = {"app:timeImageText"}, requireAll = false)
+    public static void updateTimeText(WidgetTimeTextView view, ArrayList<Integer> timeRes) {
+        if (view != null) {
+            view.updateTextTime(timeRes);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644 (file)
index 0000000..1f6bb29
--- /dev/null
@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="78.5885"
+                android:endY="90.9159"
+                android:startX="48.7653"
+                android:startY="61.0927"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+</vector>
diff --git a/app/src/main/res/drawable/ic_account_circle.xml b/app/src/main/res/drawable/ic_account_circle.xml
new file mode 100644 (file)
index 0000000..46a9558
--- /dev/null
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="120dp"
+        android:height="120dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644 (file)
index 0000000..0d025f9
--- /dev/null
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#008577"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/app/src/main/res/drawable/ic_no_sim_card.xml b/app/src/main/res/drawable/ic_no_sim_card.xml
new file mode 100644 (file)
index 0000000..3d66e2d
--- /dev/null
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M889.6,866.99a20.48,20.48 0,0 0,0 -29.87L186.88,134.4a20.48,20.48 0,0 0,-29.87 0l-22.61,22.61a20.48,20.48 0,0 0,0 29.87l73.81,74.24 -55.04,55.04A85.33,85.33 0,0 0,128 376.75L128,853.33a85.33,85.33 0,0 0,85.33 85.33h512a85.33,85.33 0,0 0,85.33 -75.95l27.31,26.88a20.48,20.48 0,0 0,29.87 0zM341.33,789.33a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-85.33a21.33,21.33 0,0 1,21.33 -21.33h42.67a21.33,21.33 0,0 1,21.33 21.33zM341.33,576a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-85.33a21.33,21.33 0,0 1,21.33 -21.33h42.67a21.33,21.33 0,0 1,21.33 21.33zM512,789.33a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-42.67a21.33,21.33 0,0 1,21.33 -21.33h42.67a21.33,21.33 0,0 1,21.33 21.33zM490.67,640h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-128a19.63,19.63 0,0 1,2.13 -8.96l83.2,85.33v51.63a21.33,21.33 0,0 1,-21.33 21.33zM682.67,789.33a21.33,21.33 0,0 1,-21.33 21.33h-42.67a21.33,21.33 0,0 1,-21.33 -21.33v-85.33a21.33,21.33 0,0 1,21.33 -21.33h11.09L682.67,735.57zM810.67,652.37L810.67,170.67a85.33,85.33 0,0 0,-85.33 -85.33L419.41,85.33a85.33,85.33 0,0 0,-60.59 25.17l-42.67,44.8z"
+      android:fillColor="#d81e06"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_sim_locking.xml b/app/src/main/res/drawable/ic_sim_locking.xml
new file mode 100644 (file)
index 0000000..d4265ad
--- /dev/null
@@ -0,0 +1,27 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+  <path
+      android:pathData="M30,24v-2.715c0,-2.615 -1.882,-4.999 -4.484,-5.259C22.523,15.726 20,18.068 20,21v3c-1,0 -2,0.895 -2,2v4c0,1.105 0.894,2 1.999,2h10C31.103,32 32,31.105 32,30v-4C32,24.895 31,24 30,24zM26,29c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1v-2c0,-0.55 0.45,-1 1,-1s1,0.45 1,1V29zM22,24v-3c0,-1.654 1.346,-3 3,-3s3,1.346 3,3v3H22z"
+      android:fillColor="#FF0000"/>
+  <path
+      android:pathData="M0.999,32H16v-2H2V7.414L7.413,2H24v12h2V1c0,-0.263 -0.107,-0.521 -0.294,-0.707C25.52,0.107 25.262,0 24.999,0h-18C6.735,0 6.478,0.107 6.291,0.293l-5.999,6C0.106,6.479 0,6.737 0,7v24c0,0.263 0.106,0.521 0.292,0.707C0.478,31.893 0.735,32 0.999,32z"
+      android:fillColor="#FFFFFF"/>
+  <path
+      android:pathData="M12,9V7c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v2c0,0.552 0.448,1 1,1S12,9.552 12,9z"
+      android:fillColor="#FFFFFF"/>
+  <path
+      android:pathData="M16,9V7c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v2c0,0.552 0.448,1 1,1S16,9.552 16,9z"
+      android:fillColor="#FFFFFF"/>
+  <path
+      android:pathData="M19,10c0.552,0 1,-0.448 1,-1V7c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v2C18,9.552 18.448,10 19,10z"
+      android:fillColor="#FFFFFF"/>
+  <path
+      android:pathData="M7,10c0.552,0 1,-0.448 1,-1V7c0,-0.552 -0.448,-1 -1,-1S6,6.448 6,7v2C6,9.552 6.448,10 7,10z"
+      android:fillColor="#FFFFFF"/>
+  <path
+      android:pathData="M18,18v-2H6.999c-0.263,0 -0.52,0.107 -0.706,0.293C6.106,16.479 6,16.737 6,17v8c0,0.263 0.106,0.521 0.292,0.707C6.478,25.893 6.735,26 6.999,26H16v-2H8v-6H18z"
+      android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/app/src/main/res/drawable/l02_battery_charging_anim.xml b/app/src/main/res/drawable/l02_battery_charging_anim.xml
new file mode 100644 (file)
index 0000000..b9ab884
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="false">
+    <item
+        android:drawable="@mipmap/l02_battery_0"
+        android:duration="150" />
+    <item
+        android:drawable="@mipmap/l02_battery_1"
+        android:duration="150" />
+    <item
+        android:drawable="@mipmap/l02_battery_2"
+        android:duration="150" />
+    <item
+        android:drawable="@mipmap/l02_battery_3"
+        android:duration="150" />
+    <item
+        android:drawable="@mipmap/l02_battery_4"
+        android:duration="150" />
+    <item
+        android:drawable="@mipmap/l02_battery_5"
+        android:duration="150" />
+</animation-list>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..362696a
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/main_content_fl"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_app_list.xml b/app/src/main/res/layout/fragment_app_list.xml
new file mode 100644 (file)
index 0000000..cf356fd
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".fragment.AppListFragment">
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/app_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_l02_main.xml b/app/src/main/res/layout/fragment_l02_main.xml
new file mode 100644 (file)
index 0000000..c5857e7
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".fragment.L02MainFragment"
+    android:orientation="vertical">
+
+    <fragment
+        android:id="@+id/l02_status_fl"
+        android:name="com.ic.launcher.fragment.l02.L02StatusBarFragment"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/status_bar_height_dm"
+        android:layout_marginTop="10dp"/>
+
+    <fragment
+        android:id="@+id/l02_watch_fl"
+        android:name="com.ic.launcher.fragment.l02.L02WatchFragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_l02_status_bar.xml b/app/src/main/res/layout/fragment_l02_status_bar.xml
new file mode 100644 (file)
index 0000000..2ccb81d
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context=".fragment.l02.L02StatusBarFragment">
+
+    <data>
+        <variable
+            name="phoneSignal"
+            type="int" />
+
+        <variable
+            name="phoneNetType"
+            type="int" />
+
+        <variable
+            name="phoneTransport"
+            type="int" />
+
+        <variable
+            name="batteryDrawable"
+            type="int" />
+
+        <variable
+            name="batteryValue"
+            type="String" />
+
+        <variable
+            name="batteryCharge"
+            type="boolean" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+
+        <com.ic.launcher.widget.WidgetPhoneStateView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.118"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:netTypeDrawable="@{phoneNetType}"
+            app:signalDrawable="@{phoneSignal}"
+            app:transportDrawable="@{phoneTransport}" />
+
+        <com.ic.launcher.widget.WidgetBatteryStateView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:batteryCharge="@{batteryCharge}"
+            app:batteryDrawable="@{batteryDrawable}"
+            app:batteryValue="@{batteryValue}"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.938"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>
diff --git a/app/src/main/res/layout/fragment_l02_watch.xml b/app/src/main/res/layout/fragment_l02_watch.xml
new file mode 100644 (file)
index 0000000..43aae6a
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context=".fragment.l02.L02WatchFragment">
+
+    <data>
+
+        <import type="java.util.ArrayList" />
+
+        <variable
+            name="timeText"
+            type="ArrayList&lt;Integer&gt;" />
+
+        <variable
+            name="watchDate"
+            type="String" />
+
+        <variable
+            name="watchWeek"
+            type="String" />
+
+        <variable
+            name="heartValue"
+            type="String" />
+
+        <variable
+            name="stepValue"
+            type="String" />
+    </data>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <com.ic.launcher.widget.WidgetTimeImageView
+            android:id="@+id/l02_time_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="25dp"
+            app:timeImageResId="@{timeText}"/>
+
+        <View
+            android:id="@+id/l02_time_sp"
+            android:layout_width="1dp"
+            android:layout_height="80dp"
+            android:layout_below="@id/l02_time_image"
+            android:layout_centerHorizontal="true" />
+
+        <TextView
+            android:id="@+id/l02_watch_data"
+            style="@style/watchDateTextStyle"
+            android:layout_below="@id/l02_time_image"
+            android:layout_marginEnd="8dp"
+            android:layout_toStartOf="@id/l02_time_sp"
+            android:text="@{watchDate}" />
+
+        <TextView
+            style="@style/watchDateTextStyle"
+            android:layout_below="@id/l02_time_image"
+            android:layout_marginStart="8dp"
+            android:layout_toEndOf="@id/l02_time_sp"
+            android:text="@{watchWeek}" />
+
+        <TextView
+            style="@style/watchDateIconTextStyle"
+            android:id="@+id/l02_heart_value"
+            android:text="@{heartValue}"
+            android:layout_toStartOf="@id/l02_time_sp"
+            android:layout_marginEnd="10dp"/>
+
+        <ImageView
+            style="@style/watchDateIconStyle"
+            android:id="@+id/l02_heart_img"
+            android:src="@mipmap/clockl02_heartrate_icon"
+            android:layout_toStartOf="@id/l02_heart_value"
+            android:layout_marginEnd="5dp"/>
+
+        <ImageView
+            style="@style/watchDateIconStyle"
+            android:id="@+id/l02_pedometer_img"
+            android:src="@mipmap/clockl02_pedometer"
+            android:layout_toEndOf="@id/l02_time_sp"/>
+
+        <TextView
+            style="@style/watchDateIconTextStyle"
+            android:id="@+id/l02_pedometer_value"
+            android:layout_marginStart="2dp"
+            android:layout_toEndOf="@id/l02_pedometer_img"
+            android:text="@{stepValue}"/>
+
+    </RelativeLayout>
+</layout>
diff --git a/app/src/main/res/layout/item_app_layout.xml b/app/src/main/res/layout/item_app_layout.xml
new file mode 100644 (file)
index 0000000..bdc49b5
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <data>
+        <variable
+            name="appTitle"
+            type="String" />
+
+        <variable
+            name="pos"
+            type="int" />
+
+        <variable name="click" type="com.ic.launcher.listener.ICheckAppItemListener"/>
+    </data>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:onClick="@{() -> click.onAppItem(pos)}">
+
+        <ImageView
+            android:id="@+id/app_icon_iv"
+            android:layout_width="180dp"
+            android:layout_height="180dp"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="30dp" />
+
+        <TextView
+            android:id="@+id/app_title_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/app_icon_iv"
+            android:layout_centerHorizontal="true"
+            android:text="@{appTitle}"
+            android:textColor="#FFFFFF"
+            android:textSize="52sp"
+            android:layout_marginTop="15dp"/>
+    </RelativeLayout>
+
+</layout>
diff --git a/app/src/main/res/layout/widget_battery_state_layout.xml b/app/src/main/res/layout/widget_battery_state_layout.xml
new file mode 100644 (file)
index 0000000..dacbb4f
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:layout_gravity="center_vertical">
+
+    <TextView
+        android:id="@+id/battery_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="#FFFFFF"
+        android:textSize="36sp"
+        android:textStyle="bold"
+        android:includeFontPadding="false"/>
+
+    <ImageView
+        android:id="@+id/battery_iv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_phone_state_layout.xml b/app/src/main/res/layout/widget_phone_state_layout.xml
new file mode 100644 (file)
index 0000000..d72721d
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <ImageView
+        android:id="@+id/signal_iv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <ImageView
+        android:id="@+id/net_type_iv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="5dp"/>
+
+    <ImageView
+        android:id="@+id/transport_iv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="2dp"/>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/widget_time_image_layout.xml b/app/src/main/res/layout/widget_time_image_layout.xml
new file mode 100644 (file)
index 0000000..0733e04
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/time_colon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true" />
+
+    <ImageView
+        android:id="@+id/time_hour_bit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toStartOf="@id/time_colon" />
+
+    <ImageView
+        android:id="@+id/time_hour_ten"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toStartOf="@id/time_hour_bit" />
+
+    <ImageView
+        android:id="@+id/time_minute_ten"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toEndOf="@id/time_colon" />
+
+    <ImageView
+        android:id="@+id/time_minute_bit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toEndOf="@id/time_minute_ten" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_time_text_layout.xml b/app/src/main/res/layout/widget_time_text_layout.xml
new file mode 100644 (file)
index 0000000..e370024
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <TextView
+        android:id="@+id/time_hour_ten_tv"
+        style="@style/timeTextHourStyle"/>
+
+    <TextView
+        style="@style/timeTextHourStyle"
+        android:id="@+id/time_hour_bit_tv"
+        android:layout_toEndOf="@id/time_hour_ten_tv" />
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/time_colon_tv"
+        android:layout_toEndOf="@id/time_hour_bit_tv"
+        android:layout_centerVertical="true"/>
+
+    <TextView
+        style="@style/timeTextMinuteStyle"
+        android:id="@+id/time_minute_ten_tv"
+        android:layout_toEndOf="@id/time_colon_tv" />
+
+    <TextView
+        style="@style/timeTextMinuteStyle"
+        android:id="@+id/time_minute_bit_tv"
+        android:layout_toEndOf="@id/time_minute_ten_tv" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644 (file)
index 0000000..eca70cf
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644 (file)
index 0000000..eca70cf
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..898f3ed
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..dffca36
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_heartrate_icon.png b/app/src/main/res/mipmap-ldpi/clockl02_heartrate_icon.png
new file mode 100644 (file)
index 0000000..eb83864
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_heartrate_icon.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_0.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_0.png
new file mode 100644 (file)
index 0000000..fe5cdeb
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_0.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_1.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_1.png
new file mode 100644 (file)
index 0000000..1575506
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_1.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_2.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_2.png
new file mode 100644 (file)
index 0000000..590caf4
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_2.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_3.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_3.png
new file mode 100644 (file)
index 0000000..1159c4f
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_3.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_4.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_4.png
new file mode 100644 (file)
index 0000000..ef74787
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_4.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_5.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_5.png
new file mode 100644 (file)
index 0000000..c5e7a8d
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_5.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_6.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_6.png
new file mode 100644 (file)
index 0000000..ab3cd09
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_6.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_7.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_7.png
new file mode 100644 (file)
index 0000000..9794ea3
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_7.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_8.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_8.png
new file mode 100644 (file)
index 0000000..97a8faa
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_8.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_hour_9.png b/app/src/main/res/mipmap-ldpi/clockl02_hour_9.png
new file mode 100644 (file)
index 0000000..0ce8178
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_hour_9.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_0.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_0.png
new file mode 100644 (file)
index 0000000..fa77bd5
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_0.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_1.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_1.png
new file mode 100644 (file)
index 0000000..fae4b0b
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_1.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_2.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_2.png
new file mode 100644 (file)
index 0000000..5628e03
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_2.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_3.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_3.png
new file mode 100644 (file)
index 0000000..0d060bf
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_3.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_4.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_4.png
new file mode 100644 (file)
index 0000000..6e0649b
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_4.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_5.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_5.png
new file mode 100644 (file)
index 0000000..905fd3b
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_5.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_6.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_6.png
new file mode 100644 (file)
index 0000000..22f863c
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_6.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_7.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_7.png
new file mode 100644 (file)
index 0000000..9f98c20
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_7.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_8.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_8.png
new file mode 100644 (file)
index 0000000..f3d38de
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_8.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_minutes_9.png b/app/src/main/res/mipmap-ldpi/clockl02_minutes_9.png
new file mode 100644 (file)
index 0000000..48e192d
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_minutes_9.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_pedometer.png b/app/src/main/res/mipmap-ldpi/clockl02_pedometer.png
new file mode 100644 (file)
index 0000000..8881488
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_pedometer.png differ
diff --git a/app/src/main/res/mipmap-ldpi/clockl02_time_colon.png b/app/src/main/res/mipmap-ldpi/clockl02_time_colon.png
new file mode 100644 (file)
index 0000000..22c4d23
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/clockl02_time_colon.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_albumn_l02.png b/app/src/main/res/mipmap-ldpi/icon_albumn_l02.png
new file mode 100644 (file)
index 0000000..c452068
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_albumn_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_alipay_l02.png b/app/src/main/res/mipmap-ldpi/icon_alipay_l02.png
new file mode 100644 (file)
index 0000000..7f7e4c4
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_alipay_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_camera_l02.png b/app/src/main/res/mipmap-ldpi/icon_camera_l02.png
new file mode 100644 (file)
index 0000000..5f242b2
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_camera_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_contacts_l02.png b/app/src/main/res/mipmap-ldpi/icon_contacts_l02.png
new file mode 100644 (file)
index 0000000..c32315e
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_contacts_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_dialer_l02.png b/app/src/main/res/mipmap-ldpi/icon_dialer_l02.png
new file mode 100644 (file)
index 0000000..b6252dc
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_dialer_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_heartrate_l02.png b/app/src/main/res/mipmap-ldpi/icon_heartrate_l02.png
new file mode 100644 (file)
index 0000000..b7e16d0
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_heartrate_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_pedometer_l02.png b/app/src/main/res/mipmap-ldpi/icon_pedometer_l02.png
new file mode 100644 (file)
index 0000000..3931075
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_pedometer_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_settings_l02.png b/app/src/main/res/mipmap-ldpi/icon_settings_l02.png
new file mode 100644 (file)
index 0000000..ad4b4f2
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_settings_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_sms_l02.png b/app/src/main/res/mipmap-ldpi/icon_sms_l02.png
new file mode 100644 (file)
index 0000000..b9459d9
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_sms_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_talk_l02.png b/app/src/main/res/mipmap-ldpi/icon_talk_l02.png
new file mode 100644 (file)
index 0000000..f415aa1
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_talk_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/icon_weather_l02.png b/app/src/main/res/mipmap-ldpi/icon_weather_l02.png
new file mode 100644 (file)
index 0000000..ad0c377
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon_weather_l02.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_battery_0.png b/app/src/main/res/mipmap-ldpi/l02_battery_0.png
new file mode 100644 (file)
index 0000000..4f0c40e
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_battery_0.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_battery_1.png b/app/src/main/res/mipmap-ldpi/l02_battery_1.png
new file mode 100644 (file)
index 0000000..2ba5cc0
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_battery_1.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_battery_2.png b/app/src/main/res/mipmap-ldpi/l02_battery_2.png
new file mode 100644 (file)
index 0000000..fdf6d6f
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_battery_2.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_battery_3.png b/app/src/main/res/mipmap-ldpi/l02_battery_3.png
new file mode 100644 (file)
index 0000000..19c7c0c
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_battery_3.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_battery_4.png b/app/src/main/res/mipmap-ldpi/l02_battery_4.png
new file mode 100644 (file)
index 0000000..a1d396d
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_battery_4.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_battery_5.png b/app/src/main/res/mipmap-ldpi/l02_battery_5.png
new file mode 100644 (file)
index 0000000..348ef53
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_battery_5.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_data_transport_0.png b/app/src/main/res/mipmap-ldpi/l02_data_transport_0.png
new file mode 100644 (file)
index 0000000..7db5b18
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_data_transport_0.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_data_transport_1.png b/app/src/main/res/mipmap-ldpi/l02_data_transport_1.png
new file mode 100644 (file)
index 0000000..ca38671
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_data_transport_1.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_data_transport_2.png b/app/src/main/res/mipmap-ldpi/l02_data_transport_2.png
new file mode 100644 (file)
index 0000000..acda3a8
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_data_transport_2.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_data_transport_3.png b/app/src/main/res/mipmap-ldpi/l02_data_transport_3.png
new file mode 100644 (file)
index 0000000..bd03153
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_data_transport_3.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_phone_type_4g.png b/app/src/main/res/mipmap-ldpi/l02_phone_type_4g.png
new file mode 100644 (file)
index 0000000..a01a9bb
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_phone_type_4g.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_signal_0.png b/app/src/main/res/mipmap-ldpi/l02_signal_0.png
new file mode 100644 (file)
index 0000000..6c38c47
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_signal_0.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_signal_1.png b/app/src/main/res/mipmap-ldpi/l02_signal_1.png
new file mode 100644 (file)
index 0000000..ab222b1
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_signal_1.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_signal_2.png b/app/src/main/res/mipmap-ldpi/l02_signal_2.png
new file mode 100644 (file)
index 0000000..07ce173
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_signal_2.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_signal_3.png b/app/src/main/res/mipmap-ldpi/l02_signal_3.png
new file mode 100644 (file)
index 0000000..97d569a
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_signal_3.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_signal_4.png b/app/src/main/res/mipmap-ldpi/l02_signal_4.png
new file mode 100644 (file)
index 0000000..dc01d22
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_signal_4.png differ
diff --git a/app/src/main/res/mipmap-ldpi/l02_signal_x.png b/app/src/main/res/mipmap-ldpi/l02_signal_x.png
new file mode 100644 (file)
index 0000000..c27b208
Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/l02_signal_x.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..64ba76f
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..dae5e08
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/l02_signal_nosim.png b/app/src/main/res/mipmap-mdpi/l02_signal_nosim.png
new file mode 100644 (file)
index 0000000..4ab4570
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/l02_signal_nosim.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..e5ed465
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..14ed0af
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..b0907ca
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..d8ae031
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..2c18de9
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644 (file)
index 0000000..beed3cd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values/attr.xml b/app/src/main/res/values/attr.xml
new file mode 100644 (file)
index 0000000..a667cf9
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="GalleryRecyclerView">
+        <attr name="helper" format="string">
+            <enum name="LinearSnapHelper" value="0" />
+            <enum name="PagerSnapHelper" value="1" />
+        </attr>
+
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644 (file)
index 0000000..c5e4e1b
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#008577</color>
+    <color name="colorPrimaryDark">#00574B</color>
+    <color name="colorAccent">#D81B60</color>
+
+    <color name="colorMainBg">#000000</color>
+</resources>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..5aa14fd
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    
+    <dimen name="status_bar_height_dm">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644 (file)
index 0000000..79c519f
--- /dev/null
@@ -0,0 +1,19 @@
+<resources>
+    <string name="app_name">IcLauncher</string>
+
+    <string name="hello_blank_fragment">Hello blank fragment</string>
+
+    <string name="app_name_contacts">联系人</string>
+    <string name="app_name_dialer">拨号</string>
+    <string name="app_name_motion">运动</string>
+    <string name="app_name_talk">微聊</string>
+    <string name="app_name_weather">天气</string>
+    <string name="app_name_heart">心率</string>
+    <string name="app_name_alipay">支付宝</string>
+    <string name="app_name_camera">照相</string>
+    <string name="app_name_album">相册</string>
+    <string name="app_name_short_message">短信</string>
+    <string name="app_name_setting">设置</string>
+
+    <string name="error_start_activity">应用程序启动失败</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644 (file)
index 0000000..478b537
--- /dev/null
@@ -0,0 +1,53 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+        <item name="android:background">@color/colorMainBg</item>
+    </style>
+
+
+    <style name="timeTextHourStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:textSize">100sp</item>
+        <item name="android:textColor">#FFFF00</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:typeface">monospace</item>
+    </style>
+
+    <style name="timeTextMinuteStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:textSize">100sp</item>
+        <item name="android:textColor">#FFFFFF</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:typeface">monospace</item>
+    </style>
+
+    <style name="watchDateTextStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:textSize">42sp</item>
+        <item name="android:textColor">#FFFFFF</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:layout_marginTop">5dp</item>
+    </style>
+
+    <style name="watchDateIconStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_alignParentBottom">true</item>
+        <item name="android:layout_marginBottom">20dp</item>
+    </style>
+
+    <style name="watchDateIconTextStyle" parent="watchDateIconStyle">
+        <item name="android:textSize">32sp</item>
+        <item name="android:textColor">#FFFFFF</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:layout_marginBottom">25dp</item>
+    </style>
+</resources>
diff --git a/app/src/test/java/com/ic/launcher/ExampleUnitTest.java b/app/src/test/java/com/ic/launcher/ExampleUnitTest.java
new file mode 100644 (file)
index 0000000..090d985
--- /dev/null
@@ -0,0 +1,17 @@
+package com.ic.launcher;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644 (file)
index 0000000..fb516be
--- /dev/null
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+        
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.5.2'
+        
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+        
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644 (file)
index 0000000..199d16e
--- /dev/null
@@ -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.
+org.gradle.jvmargs=-Xmx1536m
+# 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
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..f6b961f
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..5f0af22
--- /dev/null
@@ -0,0 +1,6 @@
+#Fri Mar 06 09:41:21 CST 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644 (file)
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# 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
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+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" -a "$nonstop" = "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"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # 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
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644 (file)
index 0000000..f955316
--- /dev/null
@@ -0,0 +1,84 @@
+@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
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@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=
+
+@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 Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_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=%*
+
+: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/settings.gradle b/settings.gradle
new file mode 100644 (file)
index 0000000..d0133d9
--- /dev/null
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name='IcLauncher'