Add Permissions on Onboading Page

This commit is contained in:
Rahul Kumar Patel
2021-03-01 14:08:13 +05:30
parent 254a5d995f
commit 38e9e8771d
15 changed files with 541 additions and 51 deletions

View File

@@ -40,8 +40,7 @@
android:name="android.permission.DELETE_PACKAGES"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" /> <!-- MIUI -->
<uses-permission android:name="com.miui.securitycenter.permission.GLOBAL_PACKAGEINSTALLER" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-feature
android:name="android.software.leanback"

View File

@@ -0,0 +1,12 @@
[
{
"id": "0",
"title": "External Storage Access",
"subtitle": "To save downloads (APKs & OBBs), export & import device configs on external storage."
},
{
"id": "1",
"title": "External Storage Manager",
"subtitle": "Required on devices running Android R+, additional to External Storage Access"
}
]

View File

@@ -47,6 +47,7 @@ import com.aurora.gplayapi.data.models.AuthData
import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.databinding.ActivityMainBinding
import com.aurora.store.util.Log
import com.aurora.store.util.Preferences
import com.aurora.store.view.ui.about.AboutActivity
import com.aurora.store.view.ui.account.AccountActivity
import com.aurora.store.view.ui.all.AppsGamesActivity
@@ -110,21 +111,10 @@ class MainActivity : BaseActivity() {
attachDrawer()
attachSearch()
checkPermission()
checkStoragePermission()
}
private fun checkPermission() = runWithPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) {
Log.i("Required permissions available")
}
private fun checkStoragePermission() {
if (Build.VERSION.SDK_INT >= 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))
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Aurora Store
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
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()
}
}

View File

@@ -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
}

View File

@@ -0,0 +1,84 @@
/*
* Aurora Store
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
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)
}
}

View File

@@ -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
}
}
}

View File

@@ -0,0 +1,167 @@
/*
* Aurora Store
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
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<Permission> = 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()
}
}
}
}

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Aurora Store
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
~
~ 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 <http://www.gnu.org/licenses/>.
~
-->
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@drawable/divider"
android:orientation="horizontal"
android:showDividers="middle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="true"
android:paddingStart="@dimen/padding_normal"
android:paddingEnd="@dimen/padding_normal"
android:text="@string/onboarding_title_permissions"
android:textAlignment="textStart"
android:textColor="?colorAccent"
android:textSize="42sp"
app:fontFamily="@font/montserrat_regular" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/AuroraTextStyle.Subtitle.Alt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="@dimen/padding_normal"
android:paddingEnd="@dimen/padding_normal"
android:text="@string/onboarding_permission_select"
android:textAlignment="textStart" />
</LinearLayout>
<com.airbnb.epoxy.EpoxyRecyclerView
android:id="@+id/epoxy_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:clipToPadding="false"
android:overScrollMode="never"
android:padding="@dimen/padding_normal"
android:scrollbars="none"
app:itemSpacing="@dimen/margin_small"
tools:listitem="@layout/view_installer" />
</LinearLayout>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Aurora Store
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
~
~ 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 <http://www.gnu.org/licenses/>.
~
-->
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@drawable/divider"
android:orientation="vertical"
android:showDividers="middle">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:includeFontPadding="true"
android:paddingStart="@dimen/padding_normal"
android:paddingEnd="@dimen/padding_normal"
android:text="@string/onboarding_title_permissions"
android:textAlignment="textStart"
android:textColor="?colorAccent"
android:textSize="42sp"
app:fontFamily="@font/montserrat_regular" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/AuroraTextStyle.Subtitle.Alt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/padding_normal"
android:paddingEnd="@dimen/padding_normal"
android:text="@string/onboarding_permission_select"
android:textAlignment="textStart" />
<com.airbnb.epoxy.EpoxyRecyclerView
android:id="@+id/epoxy_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:padding="@dimen/padding_normal"
android:scrollbars="none"
app:itemSpacing="@dimen/margin_small"
tools:listitem="@layout/view_installer" />
</LinearLayout>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Aurora Store
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
~
~ 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 <http://www.gnu.org/licenses/>.
~
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/margin_xxsmall"
android:paddingBottom="@dimen/margin_xxsmall">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/img"
android:layout_width="@dimen/icon_size_default"
android:layout_height="@dimen/icon_size_default"
android:layout_marginStart="@dimen/margin_small"
android:layout_marginEnd="@dimen/margin_small" />
<LinearLayout
android:id="@+id/permission_labels"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="@id/img"
android:orientation="vertical"
android:textAppearance="@style/TextAppearance.Aurora.Line1" />
</RelativeLayout>

View File

@@ -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" />

View File

@@ -20,23 +20,34 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/margin_xxsmall"
android:paddingBottom="@dimen/margin_xxsmall">
android:background="@drawable/bg_outlined_padded"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/img"
android:layout_width="@dimen/icon_size_default"
android:layout_height="@dimen/icon_size_default"
android:layout_marginStart="@dimen/margin_small"
android:layout_marginEnd="@dimen/margin_small" />
<LinearLayout
android:id="@+id/permission_labels"
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/line1"
style="@style/AuroraTextStyle.Subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="@id/img"
android:orientation="vertical"
android:textAppearance="@style/TextAppearance.Aurora.Line1" />
</RelativeLayout>
android:layout_toStartOf="@id/btn_action" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/line2"
style="@style/AuroraTextStyle.Line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/line1"
android:layout_alignStart="@id/line1"
android:layout_alignEnd="@id/line1"
android:maxLines="5"
android:layout_marginTop="@dimen/margin_xxsmall" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_action"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/margin_small"
android:text="@string/action_grant" />
</RelativeLayout>

View File

@@ -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" />
</RelativeLayout>

View File

@@ -79,6 +79,8 @@
<string name="action_filter_rating">"Ratings"</string>
<string name="action_finish">"Finish"</string>
<string name="action_get_local_apk">"Save App bundle"</string>
<string name="action_grant">"Grant"</string>
<string name="action_granted">"Granted"</string>
<string name="action_home">"Home"</string>
<string name="action_ignore">"Ignore"</string>
<string name="action_ignore_version">Ignore version</string>
@@ -241,13 +243,22 @@
<string name="notification_installation_auto">"Click to install"</string>
<string name="onboarding_installer_select">"Select a suitable installer"</string>
<string name="onboarding_permission_select">"Aurora Store requires following permissions"</string>
<string name="onboarding_theme_select">"Select what you like"</string>
<string name="onboarding_title_accent">"Accent"</string>
<string name="onboarding_title_installer">"Installer"</string>
<string name="onboarding_title_permissions">"Permissions"</string>
<string name="onboarding_title_theme">"Themes"</string>
<string name="onboarding_title_welcome">"Welcome"</string>
<string name="onboarding_welcome_select">"How you doing?"</string>
<string name="onboarding_permission_esa">"External Storage Access"</string>
<string name="onboarding_permission_esa_desc">"To save downloads (APKs &amp; OBBs), export &amp; import device configs on external storage."</string>
<string name="onboarding_permission_esm">"External Storage Manager"</string>
<string name="onboarding_permission_esm_desc">"Required on devices running Android R+, additional to External Storage Access"</string>
<string name="onboarding_permission_installer">"Installer Permission"</string>
<string name="onboarding_permission_installer_desc">"Allow installing apps from Aurora Store"</string>
<string name="pref_abandon_session">"Force clear installation sessions"</string>
<string name="pref_abandon_session_desc">"Clear abandon or pending installation sessions"</string>
<string name="pref_app_download">"Downloads"</string>
@@ -328,5 +339,6 @@
<string name="toast_apk_whitelisted">"Whitelisted"</string>
<string name="toast_clipboard_copied">"Copied to clipboard"</string>
<string name="toast_developer_setting_failed">"Failed to open developer settings, make sure it is enabled from device settings."</string>
<string name="toast_permission_granted">"Permission granted"</string>
<string name="toast_spoof_applied">"Device spoof applied successfully."</string>
</resources>