recently i have bought a source code and applying some changes and tested the app, everything worked perfect! except that i don't actually get notifications on the app the whole time but i will find a solution for that later... after trying to upload my app on Google Play it said that i have to have API level 29 as a minimum while i'm only having 27, i changed it by going to Project Structure and following the steps and when i tested the app on my phone, it opens normally but once i click on "menu" button it get crashed! i have searched a lot about the errors i found on the logcat but nothing worked for me. Hope you help me.
Errors on Logcat :
2020-07-22 14:43:07.004 9831-9831/? E/Zygote: isWhitelistProcess - Process is Whitelisted2020-07-22 14:43:07.006 9831-9831/? E/Zygote: accessInfo : 12020-07-22 14:43:11.641 9831-9831/com.reflection.water.time E/chromium: [ERROR:filesystem_posix.cc(62)] mkdir /data/user/0/com.reflection.water.time/cache/WebView/Crashpad: No such file or directory (2)2020-07-22 14:43:23.714 9831-9831/com.reflection.water.time E/chromium: [ERROR:aw_browser_terminator.cc(125)] Renderer process (9974) crash detected (code -1).2020-07-22 14:43:28.232 9831-9831/com.reflection.water.time E/ViewRootImpl: sendUserActionEvent() returned.2020-07-22 14:43:33.482 9831-9831/com.reflection.water.time E/ViewRootImpl: sendUserActionEvent() returned.2020-07-22 14:43:44.827 9831-9831/com.reflection.water.time E/AndroidRuntime: FATAL EXCEPTION: main Process: com.reflection.water.time, PID: 9831 java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed at android.graphics.Canvas.checkValidClipOp(Canvas.java:779) at android.graphics.Canvas.clipPath(Canvas.java:1007) at co.ceryle.radiorealbutton.RoundedCornerLayout.dispatchDraw(RoundedCornerLayout.java:80) at android.view.View.buildDrawingCacheImpl(View.java:21131) at android.view.View.buildDrawingCache(View.java:20997) at android.view.View.draw(View.java:21586) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:2023) at android.view.View.draw(View.java:21871) at android.view.View.updateDisplayListIfDirty(View.java:20741) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.draw(View.java:21871) at android.view.View.updateDisplayListIfDirty(View.java:20741) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1246) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.updateDisplayListIfDirty(View.java:20727) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.updateDisplayListIfDirty(View.java:20727) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.updateDisplayListIfDirty(View.java:20727) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.updateDisplayListIfDirty(View.java:20727) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.updateDisplayListIfDirty(View.java:20727) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.updateDisplayListIfDirty(View.java:20727) at android.view.View.draw(View.java:21594) at android.view.ViewGroup.drawChild(ViewGroup.java:4558) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4333) at android.view.View.draw(View.java:21871) at com.android.internal.policy.DecorView.draw(DecorView.java:1129) at android.view.View.updateDisplayListIfDirty(View.java:20741) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:725) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:731) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:840) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3968) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3742) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3053) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1916) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8554) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949) at android.view.Choreographer.doCallbacks(Choreographer.java:761) at android.view.Choreographer.doFrame(Choreographer.java:696) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7078)2020-07-22 14:43:44.827 9831-9831/com.reflection.water.time E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.reflection.water.time"><uses-permission android:name="android.permission.VIBRATE"/><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/><application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"><activity android:name="com.reflection.water.time.WalkThroughActivity" android:screenOrientation="portrait"></activity><activity android:name="com.reflection.water.time.StatsActivity" android:theme="@style/MainTheme" android:screenOrientation="portrait"></activity><activity android:name="com.reflection.water.time.InitUserInfoActivity" android:screenOrientation="portrait"></activity><activity android:name="com.reflection.water.time.MainActivity" android:theme="@style/MainTheme" android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><receiver android:name="com.reflection.water.time.recievers.NotifierReceiver"/><receiver android:name="com.reflection.water.time.recievers.BootReceiver"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver><meta-data android:name="com.google.android.gms.ads.AD_MANAGER_APP" android:value="true"/><meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-3940256099942544~3347511713"/><uses-library android:name="org.apache.http.legacy" android:required="false"/></application></manifest>
MainActivity :
package com.reflection.water.timeimport android.content.Intentimport android.content.SharedPreferencesimport android.os.Bundleimport android.os.Handlerimport android.text.TextUtilsimport android.util.TypedValueimport android.view.LayoutInflaterimport android.widget.LinearLayoutimport androidx.appcompat.app.AlertDialogimport androidx.appcompat.app.AppCompatActivityimport com.reflection.water.time.fragments.BottomSheetFragmentimport com.reflection.water.time.helpers.AlarmHelperimport com.reflection.water.time.helpers.SqliteHelperimport com.reflection.water.time.utils.AdsUtilityimport com.reflection.water.time.utils.AppUtilsimport com.daimajia.androidanimations.library.Techniquesimport com.daimajia.androidanimations.library.YoYoimport com.google.android.gms.ads.MobileAdsimport com.google.android.material.snackbar.Snackbarimport com.google.android.material.textfield.TextInputLayoutimport kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() { private var totalIntake: Int = 0 private var inTook: Int = 0 private lateinit var sharedPref: SharedPreferences private lateinit var sqliteHelper: SqliteHelper private lateinit var dateNow: String private var notificStatus: Boolean = false private var selectedOption: Int? = null private var snackbar: Snackbar? = null private var doubleBackToExitPressedOnce = false private lateinit var banner : LinearLayout override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) MobileAds.initialize(this, AdsUtility.admobAppId) sharedPref = getSharedPreferences(AppUtils.USERS_SHARED_PREF, AppUtils.PRIVATE_MODE) sqliteHelper = SqliteHelper(this) AdsUtility.InterstitialAdmob(this) totalIntake = sharedPref.getInt(AppUtils.TOTAL_INTAKE, 0) if (sharedPref.getBoolean(AppUtils.FIRST_RUN_KEY, true)) { startActivity(Intent(this, WalkThroughActivity::class.java)) finish() } else if (totalIntake <= 0) { startActivity(Intent(this, InitUserInfoActivity::class.java)) finish() } dateNow = AppUtils.getCurrentDate()!! banner = findViewById(R.id.banner) AdsUtility.admobBannerCall(this, banner) } fun updateValues() { totalIntake = sharedPref.getInt(AppUtils.TOTAL_INTAKE, 0) inTook = sqliteHelper.getIntook(dateNow) setWaterLevel(inTook, totalIntake) } override fun onStart() { super.onStart() val outValue = TypedValue() applicationContext.theme.resolveAttribute( android.R.attr.selectableItemBackground, outValue, true ) notificStatus = sharedPref.getBoolean(AppUtils.NOTIFICATION_STATUS_KEY, true) val alarm = AlarmHelper() if (!alarm.checkAlarm(this) && notificStatus) { btnNotific.setImageDrawable(getDrawable(R.drawable.ic_bell)) alarm.setAlarm( this, sharedPref.getInt(AppUtils.NOTIFICATION_FREQUENCY_KEY, 30).toLong() ) } if (notificStatus) { btnNotific.setImageDrawable(getDrawable(R.drawable.ic_bell)) } else { btnNotific.setImageDrawable(getDrawable(R.drawable.ic_bell_disabled)) } sqliteHelper.addAll(dateNow, 0, totalIntake) updateValues() btnMenu.setOnClickListener { val bottomSheetFragment = BottomSheetFragment( this ) bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.tag) AdsUtility.showIntestitialAds() } fabAdd.setOnClickListener { if (selectedOption != null) { if ((inTook * 100 / totalIntake) <= 140) { if (sqliteHelper.addIntook(dateNow, selectedOption!!) > 0) { inTook += selectedOption!! setWaterLevel(inTook, totalIntake) Snackbar.make(it, "Your water intake was saved...!!", Snackbar.LENGTH_SHORT) .show() } } else { Snackbar.make(it, "You already achieved the goal", Snackbar.LENGTH_SHORT).show() } selectedOption = null tvCustom.text = "Custom" op50ml.background = getDrawable(outValue.resourceId) op100ml.background = getDrawable(outValue.resourceId) op150ml.background = getDrawable(outValue.resourceId) op200ml.background = getDrawable(outValue.resourceId) op250ml.background = getDrawable(outValue.resourceId) opCustom.background = getDrawable(outValue.resourceId) } else { YoYo.with(Techniques.Shake) .duration(700) .playOn(cardView) Snackbar.make(it, "Please select an option", Snackbar.LENGTH_SHORT).show() } } btnNotific.setOnClickListener { notificStatus = !notificStatus sharedPref.edit().putBoolean(AppUtils.NOTIFICATION_STATUS_KEY, notificStatus).apply() if (notificStatus) { btnNotific.setImageDrawable(getDrawable(R.drawable.ic_bell)) Snackbar.make(it, "Notification Enabled..", Snackbar.LENGTH_SHORT).show() alarm.setAlarm( this, sharedPref.getInt(AppUtils.NOTIFICATION_FREQUENCY_KEY, 30).toLong() ) } else { btnNotific.setImageDrawable(getDrawable(R.drawable.ic_bell_disabled)) Snackbar.make(it, "Notification Disabled..", Snackbar.LENGTH_SHORT).show() alarm.cancelAlarm(this) } } btnStats.setOnClickListener { startActivity(Intent(this, StatsActivity::class.java)) AdsUtility.showIntestitialAds() } op50ml.setOnClickListener { if (snackbar != null) { snackbar?.dismiss() } selectedOption = 50 op50ml.background = getDrawable(R.drawable.option_select_bg) op100ml.background = getDrawable(outValue.resourceId) op150ml.background = getDrawable(outValue.resourceId) op200ml.background = getDrawable(outValue.resourceId) op250ml.background = getDrawable(outValue.resourceId) opCustom.background = getDrawable(outValue.resourceId) } op100ml.setOnClickListener { if (snackbar != null) { snackbar?.dismiss() } selectedOption = 100 op50ml.background = getDrawable(outValue.resourceId) op100ml.background = getDrawable(R.drawable.option_select_bg) op150ml.background = getDrawable(outValue.resourceId) op200ml.background = getDrawable(outValue.resourceId) op250ml.background = getDrawable(outValue.resourceId) opCustom.background = getDrawable(outValue.resourceId) } op150ml.setOnClickListener { if (snackbar != null) { snackbar?.dismiss() } selectedOption = 150 op50ml.background = getDrawable(outValue.resourceId) op100ml.background = getDrawable(outValue.resourceId) op150ml.background = getDrawable(R.drawable.option_select_bg) op200ml.background = getDrawable(outValue.resourceId) op250ml.background = getDrawable(outValue.resourceId) opCustom.background = getDrawable(outValue.resourceId) } op200ml.setOnClickListener { if (snackbar != null) { snackbar?.dismiss() } selectedOption = 200 op50ml.background = getDrawable(outValue.resourceId) op100ml.background = getDrawable(outValue.resourceId) op150ml.background = getDrawable(outValue.resourceId) op200ml.background = getDrawable(R.drawable.option_select_bg) op250ml.background = getDrawable(outValue.resourceId) opCustom.background = getDrawable(outValue.resourceId) } op250ml.setOnClickListener { if (snackbar != null) { snackbar?.dismiss() } selectedOption = 250 op50ml.background = getDrawable(outValue.resourceId) op100ml.background = getDrawable(outValue.resourceId) op150ml.background = getDrawable(outValue.resourceId) op200ml.background = getDrawable(outValue.resourceId) op250ml.background = getDrawable(R.drawable.option_select_bg) opCustom.background = getDrawable(outValue.resourceId) } opCustom.setOnClickListener { if (snackbar != null) { snackbar?.dismiss() } val li = LayoutInflater.from(this) val promptsView = li.inflate(R.layout.custom_input_dialog, null) val alertDialogBuilder = AlertDialog.Builder(this) alertDialogBuilder.setView(promptsView) val userInput = promptsView .findViewById(R.id.etCustomInput) as TextInputLayout alertDialogBuilder.setPositiveButton("OK") { dialog, id -> val inputText = userInput.editText!!.text.toString() if (!TextUtils.isEmpty(inputText)) { tvCustom.text = "${inputText} ml" selectedOption = inputText.toInt() } }.setNegativeButton("Cancel") { dialog, id -> dialog.cancel() } val alertDialog = alertDialogBuilder.create() alertDialog.show() op50ml.background = getDrawable(outValue.resourceId) op100ml.background = getDrawable(outValue.resourceId) op150ml.background = getDrawable(outValue.resourceId) op200ml.background = getDrawable(outValue.resourceId) op250ml.background = getDrawable(outValue.resourceId) opCustom.background = getDrawable(R.drawable.option_select_bg) } } private fun setWaterLevel(inTook: Int, totalIntake: Int) { YoYo.with(Techniques.SlideInDown) .duration(500) .playOn(tvIntook) tvIntook.text = "$inTook" tvTotalIntake.text = "/$totalIntake ml" val progress = ((inTook / totalIntake.toFloat()) * 100).toInt() YoYo.with(Techniques.Pulse) .duration(500) .playOn(intakeProgress) intakeProgress.currentProgress = progress if ((inTook * 100 / totalIntake) > 140) { Snackbar.make(main_activity_parent, "You achieved the goal", Snackbar.LENGTH_SHORT) .show() } } override fun onBackPressed() { if (doubleBackToExitPressedOnce) { super.onBackPressed() return } this.doubleBackToExitPressedOnce = true Snackbar.make( this.window.decorView.findViewById(android.R.id.content),"Please click BACK again to exit", Snackbar.LENGTH_SHORT ).show() Handler().postDelayed({ doubleBackToExitPressedOnce = false }, 1000) }}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main_activity_parent" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/ic_app_bg" tools:context="com.reflection.water.time.MainActivity"><ImageView android:id="@+id/btnMenu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:layout_marginEnd="8dp" android:background="?attr/selectableItemBackground" android:padding="4dp" android:src="@drawable/ic_settings" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" />
build.gradle :
apply plugin: 'kotlin-android'apply plugin: 'kotlin-android-extensions'android { compileSdkVersion 29 defaultConfig { applicationId "com.reflection.water.time" minSdkVersion 21 targetSdkVersion 29 versionCode 5 versionName "1.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }}