diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9d5bfeb2f..6bc41341a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -40,8 +40,7 @@
android:name="android.permission.DELETE_PACKAGES"
tools:ignore="ProtectedPermissions" />
-
-
+
= Build.VERSION_CODES.R) {
- if (!Environment.isExternalStorageManager())
- startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
+ /*Check only if download to external storage is enabled*/
+ if (Preferences.getBoolean(this, Preferences.PREFERENCE_DOWNLOAD_EXTERNAL)) {
+ checkExternalStorageAccessPermission()
+ checkExternalStorageManagerPermission()
}
}
@@ -232,17 +222,17 @@ class MainActivity : BaseActivity() {
}
}
- private fun pickExternalFileDir() {
- val getContentIntent = Intent(Intent.ACTION_GET_CONTENT)
- getContentIntent.type = "*/*"
- getContentIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
- getContentIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true)
- getContentIntent.addCategory(Intent.CATEGORY_OPENABLE)
- startActivityForResult(
- Intent.createChooser(
- getContentIntent,
- "Aurora Store - External Storage Access"
- ), 1337
- )
+ private fun checkExternalStorageAccessPermission() = runWithPermissions(
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ) {
+ Log.i("Required permissions available")
+ }
+
+ private fun checkExternalStorageManagerPermission() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ if (!Environment.isExternalStorageManager())
+ startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/aurora/store/data/model/Permission.kt b/app/src/main/java/com/aurora/store/data/model/Permission.kt
new file mode 100644
index 000000000..ff00f29ed
--- /dev/null
+++ b/app/src/main/java/com/aurora/store/data/model/Permission.kt
@@ -0,0 +1,37 @@
+/*
+ * Aurora Store
+ * Copyright (C) 2021, Rahul Kumar Patel
+ *
+ * Aurora Store 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Aurora Store 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 Aurora Store. If not, see .
+ *
+ */
+
+package com.aurora.store.data.model
+
+data class Permission(
+ var id: Int,
+ var title: String,
+ var subtitle: String
+) {
+ override fun equals(other: Any?): Boolean {
+ return when (other) {
+ is Permission -> other.id == id
+ else -> false
+ }
+ }
+
+ override fun hashCode(): Int {
+ return id.hashCode()
+ }
+}
diff --git a/app/src/main/java/com/aurora/store/view/custom/layouts/PermissionGroup.kt b/app/src/main/java/com/aurora/store/view/custom/layouts/PermissionGroup.kt
index 26840b18c..83895eeb4 100644
--- a/app/src/main/java/com/aurora/store/view/custom/layouts/PermissionGroup.kt
+++ b/app/src/main/java/com/aurora/store/view/custom/layouts/PermissionGroup.kt
@@ -70,7 +70,7 @@ class PermissionGroup : LinearLayout {
}
private fun init() {
- inflate(context, R.layout.view_permission, this)
+ inflate(context, R.layout.layout_permission, this)
packageManager = context.packageManager
}
diff --git a/app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt b/app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt
new file mode 100644
index 000000000..08aa592d7
--- /dev/null
+++ b/app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt
@@ -0,0 +1,84 @@
+/*
+ * Aurora Store
+ * Copyright (C) 2021, Rahul Kumar Patel
+ *
+ * Aurora Store 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Aurora Store 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 Aurora Store. If not, see .
+ *
+ */
+
+package com.aurora.store.view.epoxy.views.preference
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.RelativeLayout
+import com.airbnb.epoxy.CallbackProp
+import com.airbnb.epoxy.ModelProp
+import com.airbnb.epoxy.ModelView
+import com.aurora.extensions.getString
+import com.aurora.store.R
+import com.aurora.store.data.model.Permission
+import com.aurora.store.databinding.ViewPermissionBinding
+import com.aurora.store.view.epoxy.views.BaseView
+
+@ModelView(
+ autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT,
+ baseModelClass = BaseView::class
+)
+class PermissionView : RelativeLayout {
+
+ private lateinit var B: ViewPermissionBinding
+
+ constructor(context: Context?) : super(context) {
+ init(context, null)
+ }
+
+ constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
+ init(context, attrs)
+ }
+
+ constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
+ context,
+ attrs,
+ defStyleAttr
+ ) {
+ init(context, attrs)
+ }
+
+ private fun init(context: Context?, attrs: AttributeSet?) {
+ val view = inflate(context, R.layout.view_permission, this)
+ B = ViewPermissionBinding.bind(view)
+ }
+
+ @ModelProp
+ fun permission(installer: Permission) {
+ B.line1.text = installer.title
+ B.line2.text = installer.subtitle
+ }
+
+ @ModelProp
+ fun isGranted(granted: Boolean) {
+ if (granted) {
+ B.btnAction.isEnabled = false
+ B.btnAction.text = getString(R.string.action_granted)
+ } else {
+ B.btnAction.isEnabled = true
+ B.btnAction.text = getString(R.string.action_grant)
+ }
+ }
+
+ @CallbackProp
+ fun click(onClickListener: OnClickListener?) {
+ B.btnAction.setOnClickListener(onClickListener)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/OnboardingActivity.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/OnboardingActivity.kt
index 0aeb1d698..a1ec82073 100644
--- a/app/src/main/java/com/aurora/store/view/ui/onboarding/OnboardingActivity.kt
+++ b/app/src/main/java/com/aurora/store/view/ui/onboarding/OnboardingActivity.kt
@@ -104,7 +104,7 @@ class OnboardingActivity : BaseActivity() {
override fun onPageSelected(position: Int) {
runOnUiThread {
B.btnBackward.isEnabled = position != 0
- if (position == 3) {
+ if (position == 4) {
B.btnForward.text = getString(R.string.action_finish)
B.btnForward.setOnClickListener {
save(PREFERENCE_INTRO, true)
@@ -169,12 +169,13 @@ class OnboardingActivity : BaseActivity() {
1 -> return InstallerFragment()
2 -> return ThemeFragment()
3 -> return AccentFragment()
+ 4 -> return PermissionsFragment()
}
return Fragment()
}
override fun getItemCount(): Int {
- return 4
+ return 5
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt
new file mode 100644
index 000000000..a56ab1cb2
--- /dev/null
+++ b/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt
@@ -0,0 +1,167 @@
+/*
+ * Aurora Store
+ * Copyright (C) 2021, Rahul Kumar Patel
+ *
+ * Aurora Store 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Aurora Store 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 Aurora Store. If not, see .
+ *
+ */
+
+package com.aurora.store.view.ui.onboarding
+
+import android.Manifest
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.os.Environment
+import android.provider.Settings
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.app.ActivityCompat
+import com.aurora.extensions.isOAndAbove
+import com.aurora.extensions.isRAndAbove
+import com.aurora.extensions.toast
+import com.aurora.store.BuildConfig
+import com.aurora.store.R
+import com.aurora.store.data.model.Permission
+import com.aurora.store.databinding.FragmentOnboardingInstallerBinding
+import com.aurora.store.view.epoxy.views.preference.PermissionViewModel_
+import com.aurora.store.view.ui.commons.BaseFragment
+import com.livinglifetechway.quickpermissions_kotlin.runWithPermissions
+
+
+class PermissionsFragment : BaseFragment() {
+
+ private lateinit var B: FragmentOnboardingInstallerBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ B = FragmentOnboardingInstallerBinding.bind(
+ inflater.inflate(
+ R.layout.fragment_onboarding_installer,
+ container,
+ false
+ )
+ )
+
+ return B.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ updateController()
+ }
+
+ private fun updateController() {
+
+ val installerList: List = listOf(
+ Permission(
+ 0,
+ getString(R.string.onboarding_permission_esa),
+ getString(R.string.onboarding_permission_esa_desc)
+ ),
+
+ Permission(
+ 1,
+ getString(R.string.onboarding_permission_esm),
+ getString(R.string.onboarding_permission_esm_desc)
+ ),
+
+ Permission(
+ 2,
+ getString(R.string.onboarding_permission_installer),
+ getString(R.string.onboarding_permission_installer_desc)
+ )
+ )
+
+ B.epoxyRecycler.withModels {
+ setFilterDuplicates(true)
+ installerList.forEach {
+ add(
+ PermissionViewModel_()
+ .id(it.id)
+ .permission(it)
+ .isGranted(
+ when (it.id) {
+ 0 -> ActivityCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ) == PackageManager.PERMISSION_GRANTED
+ 1 -> isRAndAbove() && Environment.isExternalStorageManager()
+ 2 -> isOAndAbove() && requireContext().packageManager.canRequestPackageInstalls()
+ else -> false
+ }
+ )
+ .click { _ ->
+ when (it.id) {
+ 0 -> checkStorageAccessPermission()
+ 1 -> checkStorageManagerPermission()
+ 2 -> checkUnknownResourceInstallation()
+ }
+ }
+ )
+ }
+ }
+ }
+
+ private fun checkStorageAccessPermission() = runWithPermissions(
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.READ_EXTERNAL_STORAGE
+ ) {
+ toast(R.string.toast_permission_granted)
+ B.epoxyRecycler.requestModelBuild()
+ }
+
+ private fun checkStorageManagerPermission() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ if (Environment.isExternalStorageManager()) {
+ toast("Permission granted")
+ } else {
+ startActivityForResult(
+ Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION),
+ 99
+ )
+ }
+ }
+ }
+
+ private fun checkUnknownResourceInstallation() {
+ if (isOAndAbove()) {
+ startActivityForResult(
+ Intent(
+ Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
+ Uri.parse("package:${BuildConfig.APPLICATION_ID}")
+ ),
+ 999
+ )
+ } else {
+ toast("Permission granted")
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ when (requestCode) {
+ 99, 999 -> {
+ toast(R.string.toast_permission_granted)
+ B.epoxyRecycler.requestModelBuild()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout-land/fragment_onboarding_permissions.xml b/app/src/main/res/layout-land/fragment_onboarding_permissions.xml
new file mode 100644
index 000000000..88f3060b8
--- /dev/null
+++ b/app/src/main/res/layout-land/fragment_onboarding_permissions.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_onboarding_permissions.xml b/app/src/main/res/layout/fragment_onboarding_permissions.xml
new file mode 100644
index 000000000..4cb1ca2b2
--- /dev/null
+++ b/app/src/main/res/layout/fragment_onboarding_permissions.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_permission.xml b/app/src/main/res/layout/layout_permission.xml
new file mode 100644
index 000000000..4f586bd5b
--- /dev/null
+++ b/app/src/main/res/layout/layout_permission.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/view_installer.xml b/app/src/main/res/layout/view_installer.xml
index f5ed4726f..280c468c4 100644
--- a/app/src/main/res/layout/view_installer.xml
+++ b/app/src/main/res/layout/view_installer.xml
@@ -55,7 +55,7 @@
android:layout_width="@dimen/icon_size_category"
android:layout_height="@dimen/icon_size_category"
android:layout_alignParentEnd="true"
- android:layout_centerInParent="true"
+ android:layout_centerVertical="true"
android:clickable="false"
android:focusable="false"
android:minWidth="0dp" />
diff --git a/app/src/main/res/layout/view_permission.xml b/app/src/main/res/layout/view_permission.xml
index 4f586bd5b..7b26cb7d6 100644
--- a/app/src/main/res/layout/view_permission.xml
+++ b/app/src/main/res/layout/view_permission.xml
@@ -20,23 +20,34 @@
+ android:background="@drawable/bg_outlined_padded"
+ android:orientation="horizontal">
-
-
-
-
+ android:layout_toStartOf="@id/btn_action" />
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_theme.xml b/app/src/main/res/layout/view_theme.xml
index 84baf03a6..362f33db2 100644
--- a/app/src/main/res/layout/view_theme.xml
+++ b/app/src/main/res/layout/view_theme.xml
@@ -45,6 +45,6 @@
android:layout_width="@dimen/icon_size_category"
android:layout_height="@dimen/icon_size_category"
android:layout_alignParentEnd="true"
- android:layout_centerInParent="true"
+ android:layout_centerVertical="true"
android:minWidth="0dp" />
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index df992e8b0..1c5f344e5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -79,6 +79,8 @@
"Ratings"
"Finish"
"Save App bundle"
+ "Grant"
+ "Granted"
"Home"
"Ignore"
Ignore version
@@ -241,13 +243,22 @@
"Click to install"
"Select a suitable installer"
+ "Aurora Store requires following permissions"
"Select what you like"
"Accent"
"Installer"
+ "Permissions"
"Themes"
"Welcome"
"How you doing?"
+ "External Storage Access"
+ "To save downloads (APKs & OBBs), export & import device configs on external storage."
+ "External Storage Manager"
+ "Required on devices running Android R+, additional to External Storage Access"
+ "Installer Permission"
+ "Allow installing apps from Aurora Store"
+
"Force clear installation sessions"
"Clear abandon or pending installation sessions"
"Downloads"
@@ -328,5 +339,6 @@
"Whitelisted"
"Copied to clipboard"
"Failed to open developer settings, make sure it is enabled from device settings."
+ "Permission granted"
"Device spoof applied successfully."
\ No newline at end of file