diff --git a/app/src/main/java/melody/offline/music/App.kt b/app/src/main/java/melody/offline/music/App.kt index f51feb2..d17eec6 100644 --- a/app/src/main/java/melody/offline/music/App.kt +++ b/app/src/main/java/melody/offline/music/App.kt @@ -129,6 +129,7 @@ class App : Application() { AnalysisUtil.logEvent(AnalysisUtil.USER_LAUNCH) app = this AppLifecycleHandler(this) + saveInstallTimeIfNeeded() initAd() CommonIpInfoUtil.shared.initIPInfo() UploadEventName.shared.init(this) @@ -155,4 +156,12 @@ class App : Application() { LoLAds.setAdConfigKey("Music")//服务器端中⼴告json的key;⻅⼴告配置json详情 LoLAds.setAdConfig(AppStore(this).adJson)//设置自定义广告配置json } + + private fun saveInstallTimeIfNeeded() {//用于弹出评分dialog的条件 + val time = AppStore(this).showRateDialogTime + if (time == 0L) {//如果time为0L,则表示安装(或者是清除数据) + val currentTime = System.currentTimeMillis() + AppStore(this).showRateDialogTime = currentTime + } + } } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/activity/LaunchActivity.kt b/app/src/main/java/melody/offline/music/activity/LaunchActivity.kt index 2d1785b..97ff315 100644 --- a/app/src/main/java/melody/offline/music/activity/LaunchActivity.kt +++ b/app/src/main/java/melody/offline/music/activity/LaunchActivity.kt @@ -1,5 +1,6 @@ package melody.offline.music.activity +import android.annotation.SuppressLint import android.content.Intent import android.os.CountDownTimer import android.os.Handler @@ -141,4 +142,9 @@ class LaunchActivity : MoBaseActivity() { } }) } + + @SuppressLint("MissingSuperCall") + override fun onBackPressed() { + + } } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt b/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt index 21bc19e..eeb381f 100644 --- a/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt +++ b/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt @@ -66,7 +66,9 @@ import melody.offline.music.util.DownloadUtil import melody.offline.music.util.FileSizeConverter import melody.offline.music.util.LogTag import melody.offline.music.view.MusicPlayerView +import melody.offline.music.view.RatingDialog import org.json.JSONObject +import java.util.concurrent.TimeUnit @OptIn(UnstableApi::class) @@ -507,4 +509,16 @@ abstract class MoBaseActivity : AppCompatActivity(), MusicPlayerView.PlaySkipFor ContextCompat.getColor(this, R.color.main_bg_color) bottomSheetDialog?.show() } + + fun showRatingDialog() { + val dialog = RatingDialog(this) + val installTime = appStore.showRateDialogTime + val currentTime = System.currentTimeMillis() + // 检测是否超过三天 + if (currentTime - installTime > TimeUnit.DAYS.toMillis(3)) { + dialog.show() + //更新为当前时间 + appStore.showRateDialogTime = System.currentTimeMillis() + } + } } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/activity/PrimaryActivity.kt b/app/src/main/java/melody/offline/music/activity/PrimaryActivity.kt index c09224f..f1acfae 100644 --- a/app/src/main/java/melody/offline/music/activity/PrimaryActivity.kt +++ b/app/src/main/java/melody/offline/music/activity/PrimaryActivity.kt @@ -22,6 +22,7 @@ class PrimaryActivity : MoBaseActivity(), SearchFragment.SearchFragmentCancelCli private val mFragments: MutableList = ArrayList() private var currentIndex: Int = 0 private var mCurrentFragment: Fragment? = null + private var shouldShowDialog = false fun getCurrentFragment(): Fragment? { if (mCurrentFragment != null) { @@ -145,6 +146,19 @@ class PrimaryActivity : MoBaseActivity(), SearchFragment.SearchFragmentCancelCli private fun activityOnResume() { addMusicPlayerViewToLayout(binding.playMusicLayout) + // 如果标志位为true,则表示用户从其他页面返回到了首页 + if (shouldShowDialog) { + // 检测并弹出Dialog + showRatingDialog() + // 重置标志位 + shouldShowDialog = false + } + } + + override fun onPause() { + super.onPause() + // 设置标志位为true,表示用户离开了首页 + shouldShowDialog = true } override fun onFragmentClick() { diff --git a/app/src/main/java/melody/offline/music/activity/SettingsActivity.kt b/app/src/main/java/melody/offline/music/activity/SettingsActivity.kt index 4af6b34..0e83494 100644 --- a/app/src/main/java/melody/offline/music/activity/SettingsActivity.kt +++ b/app/src/main/java/melody/offline/music/activity/SettingsActivity.kt @@ -13,6 +13,7 @@ import melody.offline.music.util.openPrivacyPolicy import melody.offline.music.util.openTermsOfService import melody.offline.music.util.sendFeedback import melody.offline.music.util.shareApp +import melody.offline.music.view.RatingDialog class SettingsActivity : AppCompatActivity() { @@ -62,6 +63,10 @@ class SettingsActivity : AppCompatActivity() { binding.tosBtn.setOnClickListener { openTermsOfService(this, TERMS_OF_SERVICE_URL) } + binding.rateUsBtn.setOnClickListener { + val dialog = RatingDialog(this) + dialog.show() + } } } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/sp/AppStore.kt b/app/src/main/java/melody/offline/music/sp/AppStore.kt index 977fb5f..6ada955 100644 --- a/app/src/main/java/melody/offline/music/sp/AppStore.kt +++ b/app/src/main/java/melody/offline/music/sp/AppStore.kt @@ -59,6 +59,12 @@ class AppStore(context: Context) { defaultValue = Constants.DEFAULT_SHOW_AD_INTERVAL_TIME ) + //记录弹出dialog的时间 + var showRateDialogTime: Long by store.long( + key = SHOW_RATE_DIALOG_TIME, + defaultValue = 0L + ) + companion object { private const val FILE_NAME = "music_oo_app" const val SEARCH_HISTORY = "search_history" @@ -69,6 +75,6 @@ class AppStore(context: Context) { const val IP_COUNTRY_CODE = "ip_country_code" const val FIRST_OPEN_IS_SUCCEED = "first_open_is_succeed" const val SHOULD_ENTER_MUSIC_PAGE = "key_should_enter_music_page" - + const val SHOW_RATE_DIALOG_TIME = "show_rate_dialog_time" } } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/util/AnalysisUtil.kt b/app/src/main/java/melody/offline/music/util/AnalysisUtil.kt index b2c3c16..aff0e71 100644 --- a/app/src/main/java/melody/offline/music/util/AnalysisUtil.kt +++ b/app/src/main/java/melody/offline/music/util/AnalysisUtil.kt @@ -34,6 +34,9 @@ object AnalysisUtil { const val SEARCH_RESULT_PV = "search_result_pv"//搜索结果曝光 const val SEARCH_RESULT_SUCCESS_ACTION = "search_result_success_action"//搜索有结果 const val SEARCH_TRIGGER = "search_trigger "//触发搜索 + const val RATING_DIALOG_SHOW = "rating_dialog_show" + const val RATING_DIALOG_OK_CLICK = "rating_dialog_ok_click" + const val RATING_DIALOG_CANCEL_CLICK = "rating_dialog_cancel_click" private const val AD_INST_SPLASH_SUCCESS = "ad_user_open_success"//首页开屏广告展示成功 diff --git a/app/src/main/java/melody/offline/music/util/OpenUrlUtil.kt b/app/src/main/java/melody/offline/music/util/OpenUrlUtil.kt index 5126db2..96d73b7 100644 --- a/app/src/main/java/melody/offline/music/util/OpenUrlUtil.kt +++ b/app/src/main/java/melody/offline/music/util/OpenUrlUtil.kt @@ -1,9 +1,11 @@ package melody.offline.music.util +import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.net.Uri import android.widget.Toast +import androidx.core.content.ContextCompat.startActivity const val PRIVACY_POLICY_URL = "https://himelody.mystrikingly.com/privacy" const val TERMS_OF_SERVICE_URL = "https://himelody.mystrikingly.com/terms" @@ -40,4 +42,14 @@ fun sendFeedback(context: Context, email: String, subject: String) { } catch (ex: android.content.ActivityNotFoundException) { Toast.makeText(context,"There is no app that supports sending emails",Toast.LENGTH_LONG).show() } +} + +fun openGooglePlay(context: Context, packageName: String) { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$packageName")) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + try { + context.startActivity(intent) + } catch (e: ActivityNotFoundException) { + e.printStackTrace() + } } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/view/RatingDialog.kt b/app/src/main/java/melody/offline/music/view/RatingDialog.kt new file mode 100644 index 0000000..4d505ad --- /dev/null +++ b/app/src/main/java/melody/offline/music/view/RatingDialog.kt @@ -0,0 +1,73 @@ +package melody.offline.music.view + +import android.app.Dialog +import android.content.Context +import android.view.LayoutInflater +import melody.offline.music.R +import melody.offline.music.databinding.DialogRatingBinding +import melody.offline.music.util.AnalysisUtil +import melody.offline.music.util.openGooglePlay +import melody.offline.music.util.sendFeedback + +class RatingDialog(private val mContext: Context) : Dialog(mContext) { + private var starType = 5 + private var binding: DialogRatingBinding = + DialogRatingBinding.inflate(LayoutInflater.from(mContext)) + + init { + setContentView(binding.root) + window?.setBackgroundDrawableResource(android.R.color.transparent) + setCanceledOnTouchOutside(false) + initClick() + } + + private fun initClick() { + binding.dialogOkBtn.setOnClickListener { + when (starType) { + 1, 2, 3 -> { + sendFeedback( + mContext, + "motaleb3024@gmail.com", + mContext.getString(R.string.app_name) + ) + } + + 4, 5 -> { + openGooglePlay(mContext, mContext.packageName) + } + } + dismiss() + + AnalysisUtil + } + binding.dialogCancelBtn.setOnClickListener { + dismiss() + } + val stars = + arrayOf(binding.star1, binding.star2, binding.star3, binding.star4, binding.star5) + + stars.forEachIndexed { index, imageView -> + //由于数组索引从0开始,而星星的评分从1开始,因此需要将index加1 + imageView.setOnClickListener { + starType = index + 1 + updateStarUi(starType) + } + } + } + + private fun updateStarUi(type: Int) { + val stars = arrayOf( + binding.star1Img, + binding.star2Img, + binding.star3Img, + binding.star4Img, + binding.star5Img + ) + stars.forEachIndexed { index, imageView -> + //当前索引是否小于type,如果是,则表示该星星需要被选中,否则表示该星星未被选中。 + val resource = + if (index < type) R.drawable.star_select_icon else R.drawable.star_unselect_icon + imageView.setImageResource(resource) + } + } +} diff --git a/app/src/main/res/drawable/drw_rating_dialog_bg.xml b/app/src/main/res/drawable/drw_rating_dialog_bg.xml new file mode 100644 index 0000000..ea089cc --- /dev/null +++ b/app/src/main/res/drawable/drw_rating_dialog_bg.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/star_select_icon.xml b/app/src/main/res/drawable/star_select_icon.xml new file mode 100644 index 0000000..a1adedd --- /dev/null +++ b/app/src/main/res/drawable/star_select_icon.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/star_unselect_icon.xml b/app/src/main/res/drawable/star_unselect_icon.xml new file mode 100644 index 0000000..fa6775b --- /dev/null +++ b/app/src/main/res/drawable/star_unselect_icon.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 6fbd31d..4b211d6 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -108,6 +108,33 @@ android:src="@drawable/back_icon" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxhdpi/rating_img.png b/app/src/main/res/mipmap-xxhdpi/rating_img.png new file mode 100644 index 0000000..8857f8c Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/rating_img.png differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 172466a..1e59cbd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ Search About Feedback + Rate Us Share Privacy Policy Terms of Service @@ -54,4 +55,7 @@ Created successfully This song already exists in this playlist. Successfully added to the playlist + Thank you for using our app. If you enjoy our service, please give us a five-star rating. Your feedback is very important to us! + Five-Star Rating + Rate the app \ No newline at end of file