From: kfl_614 Date: Sun, 22 Mar 2020 11:05:19 +0000 (+0800) Subject: 1.IcLauncher 未完成右滑动的时候没有显示APP列表。 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=9d1d3258920bdb3be1818e20474fc01f7d26cba2;p=launcher4.git 1.IcLauncher 未完成右滑动的时候没有显示APP列表。 Signed-off-by: kfl_614 --- 9d1d3258920bdb3be1818e20474fc01f7d26cba2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -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 index 0000000..d400110 --- /dev/null +++ b/.idea/.name @@ -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 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..d291b3d --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..687d49e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..bb500df --- /dev/null +++ b/app/build.gradle @@ -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 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -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 index 0000000..1128a6a --- /dev/null +++ b/app/src/androidTest/java/com/ic/launcher/ExampleInstrumentedTest.java @@ -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 Testing documentation + */ +@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 index 0000000..5184a30 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + \ 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 index 0000000..134dc0c --- /dev/null +++ b/app/src/main/java/com/ic/launcher/IcLauncherApplication.java @@ -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 index 0000000..f47e5d8 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/MainActivity.java @@ -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 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 index 0000000..ecdc53d --- /dev/null +++ b/app/src/main/java/com/ic/launcher/adapter/AppInfoAdapter.java @@ -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 { + private static final String TAG = "AppInfoAdapter"; + + private Context mContext; + private List appArray; + private ICheckAppItemListener mListener; + + public AppInfoAdapter(Context context,ICheckAppItemListener listener) { + this.mContext = context; + appArray = new ArrayList<>(); + this.mListener = listener; + } + + public void updateAppInfoList(List 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 index 0000000..239ad06 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/configure/l02/L02AppInfo.java @@ -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 mL02DefaultAppList = new ArrayList() { + { + //联系人 + 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 index 0000000..ba58d9e --- /dev/null +++ b/app/src/main/java/com/ic/launcher/configure/l02/L02Icon.java @@ -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 index 0000000..394197a --- /dev/null +++ b/app/src/main/java/com/ic/launcher/entity/AppInfoEntity.java @@ -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 index 0000000..3bd0537 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/fragment/AppListFragment.java @@ -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 index 0000000..8027c59 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/fragment/L02MainFragment.java @@ -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 index 0000000..bda1c9c --- /dev/null +++ b/app/src/main/java/com/ic/launcher/fragment/l02/L02StatusBarFragment.java @@ -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 index 0000000..0183986 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/fragment/l02/L02WatchFragment.java @@ -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 index 0000000..3622e12 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/listener/IChangeMainFragmentListener.java @@ -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 index 0000000..a75a899 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/listener/ICheckAppItemListener.java @@ -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 index 0000000..dab2a74 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/listener/MainClockGestureDetectorImpl.java @@ -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 index 0000000..549e742 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/mode/AppListModel.java @@ -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> mObsAppInfoList; + + public AppListModel(@NonNull Application application, + @NonNull AppListPresenter appListPresenter) { + super(application); + this.appListPresenter = appListPresenter; + mObsAppInfoList = appListPresenter.getObsAppInfoList(); + } + + public LiveData> 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 create(@NonNull Class 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 index 0000000..6c02a44 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/mode/StateBarModel.java @@ -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 mObsPhoneTypeID; + private final LiveData mObsPhoneSignalID; + private final LiveData mObsPhoneTransportID; + + private final LiveData mObsBatteryValue; + private final LiveData mObsBatteryCharging; + private final LiveData 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 getObsPhoneTypeID() { + return mObsPhoneTypeID; + } + + public LiveData getObsPhoneSignalID() { + return mObsPhoneSignalID; + } + + public LiveData getObsPhoneTransportID() { + return mObsPhoneTransportID; + } + + public LiveData getObsBatteryValue() { + return mObsBatteryValue; + } + + public LiveData getObsBatteryCharging() { + return mObsBatteryCharging; + } + + public LiveData 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 create(@NonNull Class 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 index 0000000..dff03e4 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/mode/WatchFaceModel.java @@ -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> mObsTime; + private final LiveData mObsYear; + private final LiveData 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> getObsTime() { + return mObsTime; + } + + public LiveData getObsYear() { + return mObsYear; + } + + public LiveData 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 create(@NonNull Class 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 index 0000000..e07f88f --- /dev/null +++ b/app/src/main/java/com/ic/launcher/presenter/AppListPresenter.java @@ -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> mObsAppInfoList; + private MutableLiveData 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> getObsAppInfoList() { + return mObsAppInfoList; + } + + public MutableLiveData 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 index 0000000..53f0f84 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/presenter/BatteryPresenter.java @@ -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 mObsBatteryValue; + private MediatorLiveData mObsBatteryCharging; + private MediatorLiveData mObsBatteryResID; + + public MediatorLiveData getObsBatteryValue() { + return mObsBatteryValue; + } + + public MediatorLiveData getObsBatteryCharging() { + return mObsBatteryCharging; + } + + public MediatorLiveData 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 index 0000000..52293bc --- /dev/null +++ b/app/src/main/java/com/ic/launcher/presenter/PhoneStatePresenter.java @@ -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 mObsPhoneTypeID; + private MediatorLiveData mObsPhoneSignalID; + private MediatorLiveData 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 getPhoneTypeObservable() { + return mObsPhoneTypeID; + } + + public LiveData getPhoneSignalObservable() { + return mObsPhoneSignalID; + } + + public LiveData 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 index 0000000..922dd9b --- /dev/null +++ b/app/src/main/java/com/ic/launcher/presenter/QueryThread.java @@ -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 index 0000000..0eda9b0 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/presenter/QueryTrafficPooler.java @@ -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 mObsPhoneTransportID; + + public QueryTrafficPooler(MediatorLiveData 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 index 0000000..be1e7ac --- /dev/null +++ b/app/src/main/java/com/ic/launcher/presenter/TimeDatePresenter.java @@ -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> mObsTime; + private MediatorLiveData mObsYear; + private MediatorLiveData mObsWeek; + + + private Context mContext; + private Calendar mTime; + private boolean mShouldRunTicker = false; + + private ArrayList timeList; + + public TimeDatePresenter(Context context) { + mContext = context; + timeList = new ArrayList<>(); + registerTimeDateReceiver(); + createTime(null); + + mObsTime = new MediatorLiveData<>(); + mObsYear = new MediatorLiveData<>(); + mObsWeek = new MediatorLiveData<>(); + } + + public MediatorLiveData> getObsTime() { + return mObsTime; + } + + public MediatorLiveData getObsYear() { + return mObsYear; + } + + public MediatorLiveData 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 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 index 0000000..bd8e8b6 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/widget/ClockWatchView.java @@ -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 index 0000000..07d4199 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/widget/WidgetBatteryStateView.java @@ -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 index 0000000..f4f5fb6 --- /dev/null +++ b/app/src/main/java/com/ic/launcher/widget/WidgetPhoneStateView.java @@ -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 index 0000000..4a8feca --- /dev/null +++ b/app/src/main/java/com/ic/launcher/widget/WidgetTimeImageView.java @@ -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 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 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 index 0000000..18bc38d --- /dev/null +++ b/app/src/main/java/com/ic/launcher/widget/WidgetTimeTextView.java @@ -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 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 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 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + 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 index 0000000..46a9558 --- /dev/null +++ b/app/src/main/res/drawable/ic_account_circle.xml @@ -0,0 +1,9 @@ + + + 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 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 index 0000000..3d66e2d --- /dev/null +++ b/app/src/main/res/drawable/ic_no_sim_card.xml @@ -0,0 +1,9 @@ + + + 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 index 0000000..d4265ad --- /dev/null +++ b/app/src/main/res/drawable/ic_sim_locking.xml @@ -0,0 +1,27 @@ + + + + + + + + + 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 index 0000000..b9ab884 --- /dev/null +++ b/app/src/main/res/drawable/l02_battery_charging_anim.xml @@ -0,0 +1,22 @@ + + + + + + + + + \ 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 index 0000000..362696a --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,8 @@ + + \ 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 index 0000000..cf356fd --- /dev/null +++ b/app/src/main/res/layout/fragment_app_list.xml @@ -0,0 +1,13 @@ + + + + + + \ 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 index 0000000..c5857e7 --- /dev/null +++ b/app/src/main/res/layout/fragment_l02_main.xml @@ -0,0 +1,22 @@ + + + + + + + + \ 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 index 0000000..2ccb81d --- /dev/null +++ b/app/src/main/res/layout/fragment_l02_status_bar.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 index 0000000..43aae6a --- /dev/null +++ b/app/src/main/res/layout/fragment_l02_watch.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 index 0000000..bdc49b5 --- /dev/null +++ b/app/src/main/res/layout/item_app_layout.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + 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 index 0000000..dacbb4f --- /dev/null +++ b/app/src/main/res/layout/widget_battery_state_layout.xml @@ -0,0 +1,23 @@ + + + + + + + + \ 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 index 0000000..d72721d --- /dev/null +++ b/app/src/main/res/layout/widget_phone_state_layout.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + 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 index 0000000..0733e04 --- /dev/null +++ b/app/src/main/res/layout/widget_time_image_layout.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + \ 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 index 0000000..e370024 --- /dev/null +++ b/app/src/main/res/layout/widget_time_text_layout.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + \ 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 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ 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 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 index 0000000..a667cf9 --- /dev/null +++ b/app/src/main/res/values/attr.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ 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 index 0000000..c5e4e1b --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,8 @@ + + + #008577 + #00574B + #D81B60 + + #000000 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..5aa14fd --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + + 48dp + \ 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 index 0000000..79c519f --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,19 @@ + + IcLauncher + + Hello blank fragment + + 联系人 + 拨号 + 运动 + 微聊 + 天气 + 心率 + 支付宝 + 照相 + 相册 + 短信 + 设置 + + 应用程序启动失败 + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..478b537 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + 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 index 0000000..090d985 --- /dev/null +++ b/app/src/test/java/com/ic/launcher/ExampleUnitTest.java @@ -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 Testing documentation + */ +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 index 0000000..fb516be --- /dev/null +++ b/build.gradle @@ -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 index 0000000..199d16e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +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 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 index 0000000..5f0af22 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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 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 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -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 index 0000000..d0133d9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +include ':app' +rootProject.name='IcLauncher'