├── app ├── .gitignore ├── src │ ├── main │ │ ├── ic_launcher-playstore.png │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── ic_default_new.png │ │ │ │ ├── bitmap_shadow_material.xml │ │ │ │ ├── bitmap_shadow_harmony.xml │ │ │ │ ├── ic_file.xml │ │ │ │ ├── ic_file_upload.xml │ │ │ │ ├── ic_launcher_foreground.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ ├── drag_mask.xml │ │ │ │ ├── harmony_ic_public_file_filled.xml │ │ │ │ └── harmony_ic_public_upload_filled.xml │ │ │ ├── values │ │ │ │ ├── dimens.xml │ │ │ │ ├── bools.xml │ │ │ │ ├── plurals.xml │ │ │ │ ├── styles_harmony.xml │ │ │ │ ├── styles.xml │ │ │ │ ├── info_strings.xml │ │ │ │ ├── styles_material3.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── themes_harmony.xml │ │ │ │ ├── attrs.xml │ │ │ │ ├── styles_material.xml │ │ │ │ ├── themes_material.xml │ │ │ │ ├── themes_material3.xml │ │ │ │ ├── themes_material2.xml │ │ │ │ └── strings.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ ├── values-v34 │ │ │ │ └── bools.xml │ │ │ ├── values-zh-rCN │ │ │ │ ├── plurals.xml │ │ │ │ ├── info_strings.xml │ │ │ │ └── strings.xml │ │ │ ├── raw │ │ │ │ └── about.html │ │ │ ├── color │ │ │ │ ├── system_window_scrim.xml │ │ │ │ ├── secondary_emphasis_disabled_background.xml │ │ │ │ ├── text_primary_selector.xml │ │ │ │ └── text_secondary_selector.xml │ │ │ ├── xml │ │ │ │ ├── locales_config.xml │ │ │ │ ├── backup_rules.xml │ │ │ │ └── data_extraction_rules.xml │ │ │ ├── menu │ │ │ │ ├── menu_main_info.xml │ │ │ │ ├── menu_legal.xml │ │ │ │ ├── menu_main_info_basic.xml │ │ │ │ └── menu_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── values-v28 │ │ │ │ ├── themes_material.xml │ │ │ │ ├── themes_material2.xml │ │ │ │ └── themes_material3.xml │ │ │ ├── values-v29 │ │ │ │ ├── themes_material.xml │ │ │ │ ├── themes_material2.xml │ │ │ │ └── themes_material3.xml │ │ │ ├── values-v26 │ │ │ │ ├── themes_material.xml │ │ │ │ ├── themes_material2.xml │ │ │ │ └── themes_material3.xml │ │ │ ├── values-night │ │ │ │ └── colors.xml │ │ │ └── layout │ │ │ │ ├── drop_mask.xml │ │ │ │ ├── item_list_harmony.xml │ │ │ │ ├── item_list_material.xml │ │ │ │ ├── activity_main_details.xml │ │ │ │ ├── activity_main_permissions.xml │ │ │ │ └── activity_main_basic.xml │ │ ├── aidl │ │ │ └── org │ │ │ │ └── ohosdev │ │ │ │ └── hapviewerandroid │ │ │ │ ├── util │ │ │ │ └── ExecuteResult.aidl │ │ │ │ └── IUserService.aidl │ │ ├── java │ │ │ └── org │ │ │ │ └── ohosdev │ │ │ │ └── hapviewerandroid │ │ │ │ ├── extensions │ │ │ │ ├── RectExtensions.kt │ │ │ │ ├── ReflectExtensions.kt │ │ │ │ ├── FragmentExtensions.kt │ │ │ │ ├── ClipDataExtensions.kt │ │ │ │ ├── DragEventExtensions.kt │ │ │ │ ├── ViewExtensions.kt │ │ │ │ ├── ShizukuExtensions.kt │ │ │ │ ├── RecyclerViewExtensions.kt │ │ │ │ ├── ActivityExtensions.kt │ │ │ │ ├── DialogExtensions.kt │ │ │ │ ├── ContentResolverExtensions.kt │ │ │ │ ├── UriExtensions.kt │ │ │ │ ├── SnackBarExtensions.kt │ │ │ │ ├── HapInfoExtensions.kt │ │ │ │ ├── FileExtensions.kt │ │ │ │ ├── ContextExtensions.kt │ │ │ │ ├── BitmapExtensions.kt │ │ │ │ └── DocumentFileExtensions.kt │ │ │ │ ├── util │ │ │ │ ├── ohos │ │ │ │ │ └── Permission.kt │ │ │ │ ├── event │ │ │ │ │ ├── SnackBarEvent.kt │ │ │ │ │ └── BaseEvent.kt │ │ │ │ ├── ExecuteResult.kt │ │ │ │ ├── SystemUtil.kt │ │ │ │ ├── highlight │ │ │ │ │ └── JSONHighlighter.kt │ │ │ │ ├── helper │ │ │ │ │ └── ShizukuServiceHelper.kt │ │ │ │ └── ShizukuUtil.kt │ │ │ │ ├── ui │ │ │ │ ├── about │ │ │ │ │ ├── AboutDialogFragment.kt │ │ │ │ │ └── AboutDialogBuilder.kt │ │ │ │ ├── common │ │ │ │ │ ├── dialog │ │ │ │ │ │ ├── AlertDialogBuilder.kt │ │ │ │ │ │ ├── RequestPermissionDialogBuilder.kt │ │ │ │ │ │ └── RequestPermissionDialogFragment.kt │ │ │ │ │ └── BaseActivity.kt │ │ │ │ └── main │ │ │ │ │ ├── BasicInfoCard.kt │ │ │ │ │ ├── PermissionsAdapter.kt │ │ │ │ │ └── MoreInfoDialogFragment.kt │ │ │ │ ├── app │ │ │ │ ├── Constant.kt │ │ │ │ ├── HapViewerApp.kt │ │ │ │ └── AppPreference.kt │ │ │ │ ├── view │ │ │ │ ├── NestedScrollView.kt │ │ │ │ ├── behavior │ │ │ │ │ └── AppBarLayoutBehavior.kt │ │ │ │ ├── AppBarLayout.kt │ │ │ │ ├── AdvancedRecyclerView.kt │ │ │ │ ├── list │ │ │ │ │ ├── ListItemGroup.kt │ │ │ │ │ └── ListItem.kt │ │ │ │ └── drawable │ │ │ │ │ └── ShadowBitmapDrawable.kt │ │ │ │ ├── service │ │ │ │ └── shizuku │ │ │ │ │ └── UserService.kt │ │ │ │ ├── manager │ │ │ │ └── ThemeManager.kt │ │ │ │ └── model │ │ │ │ └── HapInfo.java │ │ └── AndroidManifest.xml │ ├── debug │ │ └── res │ │ │ ├── values-zh-rCN │ │ │ └── strings.xml │ │ │ └── values │ │ │ └── strings.xml │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── ohosdev │ │ │ └── hapviewerandroid │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── org │ │ └── ohosdev │ │ └── hapviewerandroid │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── harmonystyle ├── .gitignore ├── consumer-rules.pro ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ │ ├── values │ │ │ │ ├── bools.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── attrs.xml │ │ │ │ ├── colors.xml │ │ │ │ └── themes.xml │ │ │ ├── values-w600dp │ │ │ │ └── bools.xml │ │ │ ├── anim │ │ │ │ ├── harmony_dialog_enter_interpolator.xml │ │ │ │ ├── harmony_menu_enter.xml │ │ │ │ ├── harmony_menu_exit.xml │ │ │ │ ├── harmony_dialog_exit.xml │ │ │ │ └── harmony_dialog_enter.xml │ │ │ ├── values-night │ │ │ │ ├── themes.xml │ │ │ │ ├── styles.xml │ │ │ │ └── colors.xml │ │ │ ├── color │ │ │ │ ├── harmony_on_background.xml │ │ │ │ └── harmony_pressed.xml │ │ │ ├── values-v28 │ │ │ │ └── themes.xml │ │ │ ├── drawable │ │ │ │ ├── harmony_divider_menu.xml │ │ │ │ ├── harmony_divider_horizontal_buttons.xml │ │ │ │ ├── harmony_divider.xml │ │ │ │ ├── harmony_button_dialog.xml │ │ │ │ ├── harmony_action_bar_item_background.xml │ │ │ │ ├── harmony_menu_choice_background_indicator.xml │ │ │ │ ├── harmony_list_choice_background_indicator.xml │ │ │ │ ├── harmony_ic_public_more.xml │ │ │ │ └── harmony_popupmenu_background.xml │ │ │ ├── values-v29 │ │ │ │ └── themes.xml │ │ │ ├── values-v26 │ │ │ │ └── themes.xml │ │ │ └── layout │ │ │ │ ├── harmony_alert_dialog_title.xml │ │ │ │ ├── harmony_alert_dialog_button_bar.xml │ │ │ │ └── harmony_alert_dialog.xml │ │ └── java │ │ │ └── org │ │ │ └── ohosdev │ │ │ └── hapviewerandroid │ │ │ └── harmonystyle │ │ │ ├── dialog │ │ │ └── AlertDialogLayout.kt │ │ │ └── drawable │ │ │ └── ShadowDrawable.kt │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── ohosdev │ │ │ └── hapviewerandroid │ │ │ └── harmonystyle │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── org │ │ └── ohosdev │ │ └── hapviewerandroid │ │ └── harmonystyle │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── .idea └── .gitignore ├── screenshot └── all.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle ├── gradle.properties ├── README.md ├── PrivacyPolicy.md └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /harmonystyle/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /harmonystyle/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /screenshot/all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/screenshot/all.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_default_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/drawable/ic_default_new.png -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 92dp 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/values/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/values-v34/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | -------------------------------------------------------------------------------- /app/src/debug/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | HAP查看器 Debug 4 | -------------------------------------------------------------------------------- /app/src/debug/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | HAP Viewer Debug 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/aidl/org/ohosdev/hapviewerandroid/util/ExecuteResult.aidl: -------------------------------------------------------------------------------- 1 | // ExecuteResult.aidl 2 | package org.ohosdev.hapviewerandroid.util; 3 | 4 | parcelable ExecuteResult; -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/westinyang/hap-viewer-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /harmonystyle/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values-w600dp/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/extensions/RectExtensions.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.extensions 2 | 3 | import android.graphics.Rect 4 | 5 | val Rect.ratio get() = width().toFloat() / height() -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rCN/plurals.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 权限申请 5 | 6 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/anim/harmony_dialog_enter_interpolator.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/util/ohos/Permission.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.util.ohos 2 | 3 | const val PREFIX_OHOS_PERMISSION = "ohos.permission." 4 | fun String.getOhosPermSortName() = 5 | if (this.startsWith(PREFIX_OHOS_PERMISSION)) this.substring(PREFIX_OHOS_PERMISSION.length) else null -------------------------------------------------------------------------------- /harmonystyle/src/main/res/color/harmony_on_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | 17 | /.vscode 18 | /keystore 19 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/extensions/ReflectExtensions.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.extensions 2 | 3 | inline fun T.setDeclaredField(name: String, value: Any?) { 4 | T::class.java.getDeclaredField(name).apply { 5 | isAccessible = true 6 | set(this@setDeclaredField, value) 7 | } 8 | } -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/util/event/SnackBarEvent.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.util.event 2 | 3 | import android.content.Context 4 | import androidx.annotation.StringRes 5 | 6 | class SnackBarEvent(val text: String) : BaseEvent() { 7 | constructor(context: Context, @StringRes resId: Int) : this(context.getString(resId)) 8 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/bitmap_shadow_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/color/text_primary_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/color/text_secondary_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values-v28/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 6 | 7 | 6 | 7 | 6 | 7 | 9 | 10 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/ui/about/AboutDialogFragment.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.ui.about 2 | 3 | import android.app.Dialog 4 | import android.os.Bundle 5 | import androidx.fragment.app.DialogFragment 6 | 7 | class AboutDialogFragment : DialogFragment() { 8 | override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { 9 | return AboutDialogBuilder(requireContext()).create() 10 | } 11 | 12 | companion object { 13 | const val TAG = "AboutDialogFragment" 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/res/values-v29/themes_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values-v26/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 9 | 10 | 8 | 8 | 8 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/ui/common/dialog/AlertDialogBuilder.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.ui.common.dialog 2 | 3 | import android.content.Context 4 | import androidx.appcompat.app.AlertDialog 5 | import org.ohosdev.hapviewerandroid.extensions.fixDialogGravityIfNeeded 6 | 7 | /** 8 | * 整个应用使用的对话框,主要添加对话框重力修正。 9 | * */ 10 | open class AlertDialogBuilder> : MaterialAlertDialogBuilderBridge { 11 | constructor(context: Context) : super(context) 12 | constructor(context: Context, overrideThemeResId: Int) : super(context, overrideThemeResId) 13 | 14 | override fun create(): AlertDialog { 15 | return super.create().apply { 16 | fixDialogGravityIfNeeded() 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/app/HapViewerApp.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.app 2 | 3 | import android.app.Application 4 | import cn.hutool.core.io.FileUtil 5 | import java.io.File 6 | 7 | class HapViewerApp : Application() { 8 | lateinit var appPreference: AppPreference 9 | 10 | override fun onCreate() { 11 | super.onCreate() 12 | instance = this 13 | appPreference = AppPreference(this) 14 | deleteExternalFilesCaches() 15 | } 16 | 17 | private fun deleteExternalFilesCaches() { 18 | File(cacheDir, DIR_PATH_EXTERNAL_FILES).deleteRecursively() 19 | externalCacheDirs.forEach { File(it, DIR_PATH_EXTERNAL_FILES).deleteRecursively() } 20 | } 21 | 22 | companion object { 23 | lateinit var instance: HapViewerApp 24 | } 25 | } -------------------------------------------------------------------------------- /harmonystyle/src/main/res/drawable/harmony_button_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @color/harmony_color_primary_dark 5 | @color/harmony_color_surface_dark 6 | @color/harmony_color_background_dark 7 | @color/harmony_color_pressed_dark 8 | @color/harmony_color_divider_dark 9 | @color/harmony_color_hovered_dark 10 | @color/harmony_color_focused_dark 11 | @color/harmony_color_common_dark 12 | 13 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /harmonystyle/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/ui/main/BasicInfoCard.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.ui.main 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.ContextMenu 6 | import com.google.android.material.card.MaterialCardView 7 | 8 | class BasicInfoCard : MaterialCardView { 9 | private val contextMenuInfo: ContextMenuInfo? by lazy { ContextMenuInfo() } 10 | 11 | constructor(context: Context) : super(context) 12 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) 13 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) 14 | 15 | override fun getContextMenuInfo(): ContextMenu.ContextMenuInfo? { 16 | return contextMenuInfo 17 | } 18 | 19 | class ContextMenuInfo : ContextMenu.ContextMenuInfo 20 | } -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/extensions/RecyclerViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.extensions 2 | 3 | import androidx.recyclerview.widget.DividerItemDecoration 4 | import androidx.recyclerview.widget.RecyclerView 5 | import com.google.android.material.divider.MaterialDividerItemDecoration 6 | import org.ohosdev.hapviewerandroid.R 7 | 8 | /** 9 | * 如果主题中已启用分割线,就应用到布局中。 10 | * */ 11 | fun RecyclerView.applyDividerIfEnabled(orientation: Int = DividerItemDecoration.VERTICAL) { 12 | if (!context.resolveBoolean(R.attr.enableDivider, false)) { 13 | return 14 | } 15 | addItemDecoration(object : MaterialDividerItemDecoration(context, orientation) { 16 | override fun shouldDrawDivider(position: Int, adapter: RecyclerView.Adapter<*>?) = 17 | adapter?.run { position != itemCount - 1 } ?: false 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -dontwarn * 24 | -dontobfuscate -------------------------------------------------------------------------------- /app/src/main/res/drawable/drag_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/drawable/harmony_action_bar_item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #29B6F6 4 | #66BB6A 5 | 6 | @color/system_window_scrim 7 | 8 | #66BB6A 9 | #42A5F5 10 | #7E57C2 11 | 12 | #a1d39a 13 | #a3c9fe 14 | #d1bcfd 15 | 16 | #5BA854 17 | #4796C4 18 | #8C55C2 19 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/drawable/harmony_menu_choice_background_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/org/ohosdev/hapviewerandroid/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("org.ohosdev.hapviewerandroid", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /harmonystyle/src/main/res/drawable/harmony_list_choice_background_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/extensions/ActivityExtensions.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.extensions 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.FragmentActivity 5 | import androidx.fragment.app.FragmentResultListener 6 | import org.ohosdev.hapviewerandroid.R 7 | import org.ohosdev.hapviewerandroid.ui.common.BaseActivity 8 | 9 | fun FragmentActivity.setFragmentResultListener(key: String, listener: (result: Bundle) -> Unit) { 10 | setFragmentResultListener(key) { _, result -> listener(result) } 11 | } 12 | 13 | fun FragmentActivity.setFragmentResultListener(key: String, listener: FragmentResultListener) { 14 | supportFragmentManager.setFragmentResultListener(key, this, listener) 15 | } 16 | 17 | fun BaseActivity.copyAndShowSnackBar(text: String?, name: String? = null): Boolean { 18 | if (text.isNullOrEmpty()) return false 19 | copyText(text) 20 | showSnackBar(getString(R.string.copied_withName, name ?: text)) 21 | return true 22 | } -------------------------------------------------------------------------------- /harmonystyle/src/androidTest/java/org/ohosdev/hapviewerandroid/harmonystyle/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.harmonystyle; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("org.ohosdev.hapviewerandroid.harmonystyle.test", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/view/NestedScrollView.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.view 2 | 3 | import android.content.Context 4 | import android.graphics.Rect 5 | import android.util.AttributeSet 6 | import androidx.core.widget.NestedScrollView as AndroiXNestedScrollView 7 | 8 | class NestedScrollView : AndroiXNestedScrollView { 9 | constructor(context: Context) : super(context) 10 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) 11 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) 12 | 13 | /** 14 | * 是否跟随焦点滚动 15 | * */ 16 | var isScrollWithFocus: Boolean = true 17 | 18 | override fun computeScrollDeltaToGetChildRectOnScreen(rect: Rect?): Int { 19 | // 解决自动跟随焦点滚动问题 20 | // https://blog.csdn.net/ZYJWR/article/details/108386309 21 | return if (isScrollWithFocus) super.computeScrollDeltaToGetChildRectOnScreen(rect) else 0 22 | } 23 | } -------------------------------------------------------------------------------- /harmonystyle/src/main/res/drawable/harmony_ic_public_more.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/harmony_ic_public_file_filled.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { url 'https://maven.aliyun.com/repository/central' } 4 | maven { url 'https://maven.aliyun.com/repository/public' } 5 | maven { url 'https://maven.aliyun.com/repository/google' } 6 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } 7 | maven { url 'https://developer.huawei.com/repo/' } 8 | google() 9 | mavenCentral() 10 | gradlePluginPortal() 11 | } 12 | } 13 | dependencyResolutionManagement { 14 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 15 | repositories { 16 | maven { url 'https://maven.aliyun.com/repository/central' } 17 | maven { url 'https://maven.aliyun.com/repository/public' } 18 | maven { url 'https://maven.aliyun.com/repository/google' } 19 | maven { url 'https://developer.huawei.com/repo/' } 20 | google() 21 | mavenCentral() 22 | } 23 | } 24 | rootProject.name = "HapViewerAndroid" 25 | include ':app' 26 | include ':harmonystyle' 27 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/drawable/harmony_popupmenu_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drop_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 19 | 20 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #039BE5 4 | #66BB6A 5 | 6 | #43A047 7 | #1E88E5 8 | #5E35B1 9 | 10 | #3b6939 11 | #39608f 12 | #66558e 13 | 14 | #64BB5C 15 | #46B1E3 16 | #AC49F5 17 | 18 | #44000000 19 | #B3000000 20 | 21 | @color/system_window_scrim_dark 22 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/extensions/DialogExtensions.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.extensions 2 | 3 | import android.app.Dialog 4 | import android.text.method.MovementMethod 5 | import android.view.Gravity 6 | import android.widget.TextView 7 | import org.ohosdev.hapviewerandroid.harmonystyle.R.attr.windowGravityBottom 8 | 9 | val Dialog.messageView: TextView get() = findViewById(android.R.id.message) 10 | 11 | var Dialog.contentSelectable 12 | get() = messageView.isTextSelectable 13 | set(value) { 14 | messageView.setTextIsSelectable(value) 15 | } 16 | 17 | var Dialog.contentMovementMethod: MovementMethod 18 | get() = messageView.movementMethod 19 | set(value) { 20 | messageView.movementMethod = value 21 | } 22 | 23 | 24 | fun Dialog.setContentAutoLinkMask(mask: Int) { 25 | messageView.apply { 26 | linksClickable = true 27 | autoLinkMask = mask 28 | } 29 | } 30 | 31 | /** 32 | * 鸿蒙风格将对话框的 Gravity 修正为底部 33 | * */ 34 | fun Dialog.fixDialogGravityIfNeeded() { 35 | if (!context.resolveBoolean(windowGravityBottom, false)) return 36 | if (window == null) throw RuntimeException("Dialog window is null") 37 | window!!.setGravity(Gravity.BOTTOM) 38 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/harmony_ic_public_upload_filled.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /harmonystyle/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | namespace 'org.ohosdev.hapviewerandroid.harmonystyle' 8 | compileSdk 34 9 | 10 | defaultConfig { 11 | minSdk 24 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | kotlinOptions { 28 | jvmTarget = JavaVersion.VERSION_1_8 29 | } 30 | } 31 | 32 | dependencies { 33 | 34 | implementation 'androidx.appcompat:appcompat:1.6.1' 35 | implementation 'com.google.android.material:material:1.11.0' 36 | implementation 'com.huawei.ui.uikit:hwradiobutton:1.0.0.500' 37 | testImplementation 'junit:junit:4.13.2' 38 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 39 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 40 | } -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/view/behavior/AppBarLayoutBehavior.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.view.behavior 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | import androidx.coordinatorlayout.widget.CoordinatorLayout 7 | import com.google.android.material.appbar.AppBarLayout 8 | 9 | 10 | class AppBarLayoutBehavior : AppBarLayout.Behavior { 11 | constructor() : super() 12 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) 13 | 14 | override fun onNestedScroll( 15 | coordinatorLayout: CoordinatorLayout, 16 | child: AppBarLayout, 17 | target: View, 18 | dxConsumed: Int, 19 | dyConsumed: Int, 20 | dxUnconsumed: Int, 21 | dyUnconsumed: Int, 22 | type: Int, 23 | consumed: IntArray 24 | ) { 25 | super.onNestedScroll( 26 | coordinatorLayout, 27 | child, 28 | target, 29 | dxConsumed, 30 | dyConsumed, 31 | dxUnconsumed, 32 | dyUnconsumed, 33 | type, 34 | consumed 35 | ) 36 | if (child.isLiftOnScroll && dyUnconsumed < 0) { 37 | child.isLifted = false 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/util/highlight/JSONHighlighter.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.util.highlight 2 | 3 | object JSONHighlighter { 4 | private const val COLOR_STRING = "#009688" 5 | private const val COLOR_KEYWORD = "#673AB7" 6 | private const val COLOR_NUMBER = "#2196F3" 7 | 8 | private val PATTERN_STRING = Regex("([^\\\\])(\"[^\"]*[^\\\\]\")") 9 | private val PATTERN_KEYWORD = Regex("\\b(true|false)\\b") 10 | private val PATTERN_NUMBER = Regex("([\\s{])(\\d+)([\\s},])") 11 | private val PATTERN_WRAP = Regex("\\n") 12 | private val PATTERN_SPACE = Regex(" ") 13 | 14 | fun highlight( 15 | jsonText: String, 16 | stringColor: String = COLOR_STRING, 17 | keywordColor: String = COLOR_KEYWORD, 18 | numberColor: String = COLOR_NUMBER 19 | ) = jsonText 20 | .replace(PATTERN_SPACE, " ") 21 | .replace(PATTERN_STRING) { "${it.groupValues[1]}${it.groupValues[2]}" } 22 | .replace(PATTERN_KEYWORD) { "${it.value}" } 23 | .replace(PATTERN_NUMBER) { "${it.groupValues[1]}${it.groupValues[2]}${it.groupValues[3]}" } 24 | .replace(PATTERN_WRAP, "
") 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/extensions/ContentResolverExtensions.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.extensions 2 | 3 | import android.content.ContentResolver 4 | import android.net.Uri 5 | import android.provider.DocumentsContract 6 | import java.io.IOException 7 | 8 | private const val TAG = "ContentResolverExtensions" 9 | 10 | /** 11 | * 获取 `_data` 列的值作为字符串并返回,一般用于获取文件路径。 12 | * */ 13 | @Throws(IOException::class) 14 | fun ContentResolver.getDataColumn(uri: Uri, selection: String? = null, selectionArgs: Array? = null) = 15 | queryForString(uri, "_data", selection, selectionArgs) 16 | 17 | /** 18 | * 从 ContentResolver 中搜索 `uri`,将`column` 的值作为字符串并返回。 19 | * @see ContentResolver.query 20 | * */ 21 | fun ContentResolver.queryForString( 22 | uri: Uri, 23 | column: String, 24 | selection: String? = null, 25 | selectionArgs: Array? = null 26 | ): String? = runCatching { 27 | return query(uri, arrayOf(column), selection, selectionArgs, null)?.use { 28 | if (it.moveToFirst() && !it.isNull(0)) { 29 | it.getString(0) 30 | } else { 31 | null 32 | } 33 | } 34 | }.onFailure { it.printStackTrace() }.getOrNull() 35 | 36 | fun ContentResolver.getDocumentName(uri: Uri) = queryForString(uri, DocumentsContract.Document.COLUMN_DISPLAY_NAME) 37 | -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/ui/common/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.ui.common 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.StringRes 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.coordinatorlayout.widget.CoordinatorLayout 7 | import com.google.android.material.snackbar.Snackbar 8 | import org.ohosdev.hapviewerandroid.manager.ThemeManager 9 | import rikka.insets.WindowInsetsHelper 10 | import rikka.layoutinflater.view.LayoutInflaterFactory 11 | 12 | abstract class BaseActivity : AppCompatActivity() { 13 | protected val themeManager: ThemeManager = ThemeManager(this) 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | layoutInflater.factory2 = LayoutInflaterFactory(delegate) 16 | .addOnViewCreatedListener(WindowInsetsHelper.LISTENER) 17 | super.onCreate(savedInstanceState) 18 | themeManager.applyTheme() 19 | } 20 | 21 | abstract val rootView: CoordinatorLayout 22 | 23 | /** 24 | * 在屏幕上显示一个 SnackBar 25 | * */ 26 | fun showSnackBar(@StringRes textId: Int): Snackbar { 27 | return showSnackBar(getString(textId)) 28 | } 29 | 30 | open fun showSnackBar(text: String): Snackbar { 31 | return Snackbar.make(rootView, text, Snackbar.LENGTH_SHORT).apply { show() } 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/org/ohosdev/hapviewerandroid/app/AppPreference.kt: -------------------------------------------------------------------------------- 1 | package org.ohosdev.hapviewerandroid.app 2 | 3 | import android.content.Context 4 | import androidx.core.content.edit 5 | import androidx.preference.PreferenceManager 6 | import org.ohosdev.hapviewerandroid.app.AppPreference.ThemeType 7 | 8 | class AppPreference(private val context: Context) { 9 | 10 | companion object { 11 | const val KEY_THEME_TYPE = "pref_theme_type" 12 | } 13 | 14 | private val sharedPreference = PreferenceManager.getDefaultSharedPreferences(context) 15 | 16 | var themeType: ThemeType 17 | get() = sharedPreference.getString(KEY_THEME_TYPE, ThemeType.HARMONY.value)!!.toThemeType() 18 | set(value) { 19 | sharedPreference.edit { this.putString(KEY_THEME_TYPE, value.value) } 20 | } 21 | 22 | enum class ThemeType(val value: String) { 23 | MATERIAL1("material1"), 24 | MATERIAL2("material2"), 25 | MATERIAL3("material3"), 26 | HARMONY("harmony") 27 | } 28 | } 29 | 30 | fun String.toThemeType(): ThemeType { 31 | return when (this) { 32 | ThemeType.MATERIAL1.value -> ThemeType.MATERIAL1 33 | ThemeType.MATERIAL2.value -> ThemeType.MATERIAL2 34 | ThemeType.MATERIAL3.value -> ThemeType.MATERIAL3 35 | ThemeType.HARMONY.value -> ThemeType.HARMONY 36 | else -> ThemeType.HARMONY 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/res/values/themes_harmony.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 26 | 27 | 8 | 9 | 13 | 14 | 15 | 18 | 19 | 24 | 25 | 26 | 30 | 31 | 36 | 37 | 38 | 41 | 42 | 50 | 51 | -------------------------------------------------------------------------------- /harmonystyle/src/main/res/layout/harmony_alert_dialog_button_bar.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | 25 | 38 | 39 |