diff --git a/app/src/main/java/io/timelimit/android/logic/AppSetupLogic.kt b/app/src/main/java/io/timelimit/android/logic/AppSetupLogic.kt index f788251..696049a 100644 --- a/app/src/main/java/io/timelimit/android/logic/AppSetupLogic.kt +++ b/app/src/main/java/io/timelimit/android/logic/AppSetupLogic.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2021 Jonas Lochmann + * TimeLimit Copyright 2019 - 2022 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ import io.timelimit.android.data.model.* import io.timelimit.android.integration.platform.NewPermissionStatus import io.timelimit.android.integration.platform.ProtectionLevel import io.timelimit.android.integration.platform.RuntimePermissionStatus +import io.timelimit.android.ui.setup.SetupUnprovisionedCheck import io.timelimit.android.ui.user.create.DefaultCategories import io.timelimit.android.util.AndroidVersion import io.timelimit.android.work.CheckUpdateWorker @@ -58,6 +59,8 @@ class AppSetupLogic(private val appLogic: AppLogic) { run { val customServerUrl = appLogic.database.config().getCustomServerUrlSync() + SetupUnprovisionedCheck.checkSync(appLogic.database) + // just for safety: delete everything except the custom server url appLogic.database.deleteAllData() diff --git a/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt b/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt index c0694a7..1e84dd9 100644 --- a/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/setup/SetupSelectModeFragment.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2021 Jonas Lochmann + * TimeLimit Copyright 2019 - 2022 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,13 +22,19 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.navigation.NavController import androidx.navigation.Navigation +import io.timelimit.android.BuildConfig import io.timelimit.android.R +import io.timelimit.android.async.Threads +import io.timelimit.android.coroutines.executeAndWait +import io.timelimit.android.coroutines.runAsync import io.timelimit.android.databinding.FragmentSetupSelectModeBinding import io.timelimit.android.extensions.safeNavigate import io.timelimit.android.logic.DefaultAppLogic @@ -37,6 +43,7 @@ import io.timelimit.android.ui.setup.privacy.PrivacyInfoDialogFragment class SetupSelectModeFragment : Fragment() { companion object { + private const val LOG_TAG = "SetupSelectModeFragment" private const val REQ_SETUP_CONNECTED_PARENT = 1 private const val REQ_SETUP_CONNECTED_CHILD = 2 private const val REQUEST_SETUP_PARENT_MODE = 3 @@ -82,18 +89,39 @@ class SetupSelectModeFragment : Fragment() { } binding.btnUninstall.setOnClickListener { - DefaultAppLogic.with(requireContext()).platformIntegration.disableDeviceAdmin() + val context = requireContext().applicationContext + val logic = DefaultAppLogic.with(requireContext()) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - startActivity( - Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:${requireContext().packageName}")) + runAsync { + try { + Threads.database.executeAndWait { SetupUnprovisionedCheck.checkSync(logic.database) } + + logic.platformIntegration.disableDeviceAdmin() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + context.startActivity( + Intent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.parse("package:${requireContext().packageName}") + ) .addCategory(Intent.CATEGORY_DEFAULT) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - ) - } else { - startActivity( - Intent(Intent.ACTION_UNINSTALL_PACKAGE, Uri.parse("package:${requireContext().packageName}")) - ) + ) + } else { + context.startActivity( + Intent( + Intent.ACTION_UNINSTALL_PACKAGE, + Uri.parse("package:${requireContext().packageName}") + ) + ) + } + } catch (ex: Exception) { + if (BuildConfig.DEBUG) { + Log.w(LOG_TAG, "reset failed", ex) + } + + Toast.makeText(context, R.string.error_general, Toast.LENGTH_SHORT).show() + } } } } diff --git a/app/src/main/java/io/timelimit/android/ui/setup/SetupUnprovisionedCheck.kt b/app/src/main/java/io/timelimit/android/ui/setup/SetupUnprovisionedCheck.kt new file mode 100644 index 0000000..ebdb14e --- /dev/null +++ b/app/src/main/java/io/timelimit/android/ui/setup/SetupUnprovisionedCheck.kt @@ -0,0 +1,29 @@ +/* + * TimeLimit Copyright 2019 - 2022 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.timelimit.android.ui.setup + +import io.timelimit.android.data.Database +import java.lang.RuntimeException + +object SetupUnprovisionedCheck { + fun checkSync(database: Database) { + if (database.config().getOwnDeviceIdSync() != null) { + throw ProvisionedException() + } + } + + class ProvisionedException: RuntimeException() +} \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/ui/setup/child/SetupRemoteChildViewModel.kt b/app/src/main/java/io/timelimit/android/ui/setup/child/SetupRemoteChildViewModel.kt index 95f5762..7388ad7 100644 --- a/app/src/main/java/io/timelimit/android/ui/setup/child/SetupRemoteChildViewModel.kt +++ b/app/src/main/java/io/timelimit/android/ui/setup/child/SetupRemoteChildViewModel.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2022 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ import io.timelimit.android.sync.ApplyServerDataStatus import io.timelimit.android.sync.network.ClientDataStatus import io.timelimit.android.sync.network.NewDeviceInfo import io.timelimit.android.sync.network.api.UnauthorizedHttpError +import io.timelimit.android.ui.setup.SetupUnprovisionedCheck class SetupRemoteChildViewModel(application: Application): AndroidViewModel(application) { private val statusInternal = MutableLiveData().apply { value = SetupRemoteChildStatus.Idle } @@ -62,6 +63,8 @@ class SetupRemoteChildViewModel(application: Application): AndroidViewModel(appl logic.database.runInTransaction { val customServerUrl = logic.database.config().getCustomServerUrlSync() + SetupUnprovisionedCheck.checkSync(logic.database) + logic.database.deleteAllData() logic.database.config().setCustomServerUrlSync(customServerUrl) logic.database.config().setOwnDeviceIdSync(registerResponse.ownDeviceId) diff --git a/app/src/main/java/io/timelimit/android/ui/setup/parent/SetupParentModeModel.kt b/app/src/main/java/io/timelimit/android/ui/setup/parent/SetupParentModeModel.kt index c0d63b2..3747221 100644 --- a/app/src/main/java/io/timelimit/android/ui/setup/parent/SetupParentModeModel.kt +++ b/app/src/main/java/io/timelimit/android/ui/setup/parent/SetupParentModeModel.kt @@ -1,5 +1,5 @@ /* - * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * TimeLimit Copyright 2019 - 2022 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ import io.timelimit.android.sync.network.ParentPassword import io.timelimit.android.sync.network.StatusOfMailAddressResponse import io.timelimit.android.sync.network.api.ConflictHttpError import io.timelimit.android.sync.network.api.UnauthorizedHttpError +import io.timelimit.android.ui.setup.SetupUnprovisionedCheck import io.timelimit.android.update.UpdateUtil import io.timelimit.android.work.PeriodicSyncInBackgroundWorker @@ -106,6 +107,8 @@ class SetupParentModeModel(application: Application): AndroidViewModel(applicati logic.database.runInTransaction { val customServerUrl = logic.database.config().getCustomServerUrlSync() + SetupUnprovisionedCheck.checkSync(logic.database) + database.deleteAllData() database.config().setCustomServerUrlSync(customServerUrl) @@ -175,6 +178,8 @@ class SetupParentModeModel(application: Application): AndroidViewModel(applicati logic.database.runInTransaction { val customServerUrl = logic.database.config().getCustomServerUrlSync() + SetupUnprovisionedCheck.checkSync(logic.database) + database.deleteAllData() database.config().setCustomServerUrlSync(customServerUrl)