aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-07-03 22:34:05 -0700
committerAllan Wang <me@allanwang.ca>2017-07-03 22:34:05 -0700
commitd024e8db464e8b0ba0133feed67896b854fd8b25 (patch)
treefcbe4828b91c566000a041989c3c28401b6b618f
parent8df185cfdc94fa937d37d8ec6ece6a2374fba189 (diff)
downloadkau-d024e8db464e8b0ba0133feed67896b854fd8b25.tar.gz
kau-d024e8db464e8b0ba0133feed67896b854fd8b25.tar.bz2
kau-d024e8db464e8b0ba0133feed67896b854fd8b25.zip
Push permission manager for release
-rw-r--r--docs/Changelog.md1
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt2
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt (renamed from library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt)2
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt7
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt72
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt5
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt5
-rw-r--r--sample/src/main/AndroidManifest.xml4
-rw-r--r--sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt29
-rw-r--r--sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt13
-rw-r--r--sample/src/main/res/values/styles.xml7
-rw-r--r--sample/src/main/res/xml/changelog.xml3
12 files changed, 129 insertions, 21 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md
index de6779d..fa9dda0 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -3,6 +3,7 @@
## v1.5
* Change snackbar builder
* Change addBundle to withArguments to match ANKO
+* Created KauIItem to replace AbstractItem
## v1.4
* Added about activities
diff --git a/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt b/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt
index 9484299..32e8745 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt
@@ -138,7 +138,7 @@ abstract class AboutActivityBase(val rClass: Class<*>, val configBuilder: Config
*/
open fun inflateMainPage(layoutInflater: LayoutInflater, parent: ViewGroup, position: Int): View {
val fastAdapter = FastItemThemedAdapter<IItem<*, *>>(configs)
- val recycler = fullLinearRecycler { adapter = fastAdapter }
+ val recycler = fullLinearRecycler(fastAdapter)
fastAdapter.add(CutoutIItem {
with(configs) {
text = string(cutoutTextRes, cutoutText)
diff --git a/library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt b/library/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt
index 7e4bda6..00b165c 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt
@@ -12,7 +12,7 @@ import com.mikepenz.fastadapter.items.AbstractItem
*
* Kotlin implementation of the [AbstractItem] to make things shorter
*/
-open class KotlinIItem<Item, VH : RecyclerView.ViewHolder>(
+open class KauIItem<Item, VH : RecyclerView.ViewHolder>(
private val type: Int,
@param:LayoutRes private val layoutRes: Int,
private val viewHolder: (v: View) -> VH
diff --git a/library/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt b/library/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt
index 7181e2c..6f93c9f 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt
@@ -18,6 +18,7 @@ internal object PermissionManager {
val pendingResults: MutableList<WeakReference<PermissionResult>> by lazy { mutableListOf<WeakReference<PermissionResult>>() }
operator fun invoke(context: Context, permissions: Array<out String>, callback: (granted: Boolean, deniedPerm: String?) -> Unit) {
+ KL.d("Requesting permissions: ${permissions.contentToString()}")
if (!buildIsMarshmallowAndUp) return callback(true, null)
val missingPermissions = permissions.filter { !context.hasPermission(it) }
if (missingPermissions.isEmpty()) return callback(true, null)
@@ -25,15 +26,15 @@ internal object PermissionManager {
if (!requestInProgress) {
requestInProgress = true
requestPermissions(context, missingPermissions.toTypedArray())
- } else KL.d("Request is postponed since another one is still in progress")
+ } else KL.d("Request is postponed since another one is still in progress; did you remember to override onRequestPermissionsResult?")
}
- @Synchronized internal fun requestPermissions(context: Context, permissions: Array<String>) {
+ @Synchronized internal fun requestPermissions(context: Context, permissions: Array<out String>) {
val activity = (context as? Activity) ?: throw KauException("Context is not an instance of an activity; cannot request permissions")
ActivityCompat.requestPermissions(activity, permissions, 1)
}
- fun onRequestPermissionsResult(context: Context, permissions: Array<String>, grantResults: IntArray) {
+ fun onRequestPermissionsResult(context: Context, permissions: Array<out String>, grantResults: IntArray) {
val count = Math.min(permissions.size, grantResults.size)
val iter = pendingResults.iterator()
while (iter.hasNext()) {
diff --git a/library/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt b/library/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt
index d466cb3..5d52ecb 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt
@@ -1,7 +1,35 @@
package ca.allanwang.kau.permissions
+import android.Manifest
import android.app.Activity
import android.content.Context
+import android.Manifest.permission
+import android.Manifest.permission.SYSTEM_ALERT_WINDOW
+import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+import android.Manifest.permission.READ_EXTERNAL_STORAGE
+import android.Manifest.permission.RECEIVE_MMS
+import android.Manifest.permission.RECEIVE_WAP_PUSH
+import android.Manifest.permission.READ_SMS
+import android.Manifest.permission.RECEIVE_SMS
+import android.Manifest.permission.SEND_SMS
+import android.Manifest.permission.BODY_SENSORS
+import android.Manifest.permission.PROCESS_OUTGOING_CALLS
+import android.Manifest.permission.USE_SIP
+import android.Manifest.permission.ADD_VOICEMAIL
+import android.Manifest.permission.WRITE_CALL_LOG
+import android.Manifest.permission.READ_CALL_LOG
+import android.Manifest.permission.CALL_PHONE
+import android.Manifest.permission.READ_PHONE_STATE
+import android.Manifest.permission.RECORD_AUDIO
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.GET_ACCOUNTS
+import android.Manifest.permission.WRITE_CONTACTS
+import android.Manifest.permission.READ_CONTACTS
+import android.Manifest.permission.WRITE_CALENDAR
+import android.Manifest.permission.READ_CALENDAR
+
+
/**
* Created by Allan Wang on 2017-07-02.
@@ -12,7 +40,7 @@ import android.content.Context
/**
* Hook that should be added inside all [Activity.onRequestPermissionsResult] so that the Permission manager can handle the responses
*/
-fun Activity.kauOnRequestPermissionsResult(permissions: Array<String>, grantResults: IntArray)
+fun Activity.kauOnRequestPermissionsResult(permissions: Array<out String>, grantResults: IntArray)
= PermissionManager.onRequestPermissionsResult(this, permissions, grantResults)
/**
@@ -23,4 +51,44 @@ fun Activity.kauOnRequestPermissionsResult(permissions: Array<String>, grantResu
* [deniedPerm] is the first denied permission, if granted is false
*/
fun Context.requestPermissions(vararg permissions: String, callback: (granted: Boolean, deniedPerm: String?) -> Unit)
- = PermissionManager(this, permissions, callback) \ No newline at end of file
+ = PermissionManager(this, permissions, callback)
+
+/**
+ * See http://developer.android.com/guide/topics/security/permissions.html#normal-dangerous for a
+ * list of 'dangerous' permissions that require a permission request on API 23.
+ */
+const val PERMISSION_READ_CALENDAR = Manifest.permission.READ_CALENDAR
+
+const val PERMISSION_WRITE_CALENDAR = Manifest.permission.WRITE_CALENDAR
+
+const val PERMISSION_CAMERA = Manifest.permission.CAMERA
+
+const val PERMISSION_READ_CONTACTS = Manifest.permission.READ_CONTACTS
+const val PERMISSION_WRITE_CONTACTS = Manifest.permission.WRITE_CONTACTS
+const val PERMISSION_GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS
+
+const val PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION
+const val PERMISSION_ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION
+
+const val PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO
+
+const val PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE
+const val PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE
+const val PERMISSION_READ_CALL_LOG = Manifest.permission.READ_CALL_LOG
+const val PERMISSION_WRITE_CALL_LOG = Manifest.permission.WRITE_CALL_LOG
+const val PERMISSION_ADD_VOICEMAIL = Manifest.permission.ADD_VOICEMAIL
+const val PERMISSION_USE_SIP = Manifest.permission.USE_SIP
+const val PERMISSION_PROCESS_OUTGOING_CALLS = Manifest.permission.PROCESS_OUTGOING_CALLS
+
+const val PERMISSION_BODY_SENSORS = Manifest.permission.BODY_SENSORS
+
+const val PERMISSION_SEND_SMS = Manifest.permission.SEND_SMS
+const val PERMISSION_RECEIVE_SMS = Manifest.permission.RECEIVE_SMS
+const val PERMISSION_READ_SMS = Manifest.permission.READ_SMS
+const val PERMISSION_RECEIVE_WAP_PUSH = Manifest.permission.RECEIVE_WAP_PUSH
+const val PERMISSION_RECEIVE_MMS = Manifest.permission.RECEIVE_MMS
+
+const val PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE
+const val PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE
+
+const val PERMISSION_SYSTEM_ALERT_WINDOW = Manifest.permission.SYSTEM_ALERT_WINDOW \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt
index 95a38da..ac8ec2e 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt
@@ -11,9 +11,8 @@ import android.view.View
import android.widget.ImageView
import android.widget.TextView
import ca.allanwang.kau.R
-import ca.allanwang.kau.iitems.KotlinIItem
+import ca.allanwang.kau.iitems.KauIItem
import ca.allanwang.kau.utils.*
-import com.mikepenz.fastadapter.items.AbstractItem
import com.mikepenz.google_material_typeface_library.GoogleMaterial
import com.mikepenz.iconics.typeface.IIcon
@@ -29,7 +28,7 @@ class SearchItem(val key: String,
val description: String? = null,
val iicon: IIcon? = GoogleMaterial.Icon.gmd_search,
val image: Drawable? = null
-) : KotlinIItem<SearchItem, SearchItem.ViewHolder>(
+) : KauIItem<SearchItem, SearchItem.ViewHolder>(
R.id.kau_item_search,
R.layout.kau_search_iitem,
{ViewHolder(it)}
diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
index bd17b92..b4752a5 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
@@ -48,7 +48,7 @@ import com.mikepenz.iconics.typeface.IIcon
@KauUtils fun View.isInvisible(): Boolean = visibility == View.INVISIBLE
@KauUtils fun View.isGone(): Boolean = visibility == View.GONE
-fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: Snackbar.() -> Unit = {}):Snackbar {
+fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: Snackbar.() -> Unit = {}): Snackbar {
val snackbar = Snackbar.make(this, text, duration)
snackbar.builder()
snackbar.show()
@@ -116,10 +116,11 @@ val CIRCULAR_OUTLINE: ViewOutlineProvider = object : ViewOutlineProvider() {
/**
* Generates a recycler view with match parent and a linearlayoutmanager, since it's so commonly used
*/
-fun Context.fullLinearRecycler(configs: RecyclerView.() -> Unit = {}): RecyclerView {
+fun Context.fullLinearRecycler(rvAdapter: RecyclerView.Adapter<*>? = null, configs: RecyclerView.() -> Unit = {}): RecyclerView {
return RecyclerView(this).apply {
layoutManager = LinearLayoutManager(this@fullLinearRecycler)
layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT)
+ if (rvAdapter != null) adapter = rvAdapter
configs()
}
} \ No newline at end of file
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 5e6eb4c..44d9416 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ca.allanwang.kau.sample">
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
<application
android:name=".SampleApp"
android:allowBackup="true"
@@ -13,7 +15,7 @@
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
- android:theme="@style/AppTheme.NoActionBar">
+ android:theme="@style/AppTheme.NoActionBar.Transparent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt
index 2fd846c..8b8d784 100644
--- a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt
+++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt
@@ -2,8 +2,14 @@ package ca.allanwang.kau.sample
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
+import ca.allanwang.kau.logging.KL
+import ca.allanwang.kau.permissions.PERMISSION_ACCESS_COARSE_LOCATION
+import ca.allanwang.kau.permissions.PERMISSION_ACCESS_FINE_LOCATION
+import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult
+import ca.allanwang.kau.permissions.requestPermissions
import ca.allanwang.kau.utils.fullLinearRecycler
import ca.allanwang.kau.utils.startActivitySlideOut
+import ca.allanwang.kau.utils.toast
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
/**
@@ -16,14 +22,29 @@ class AnimActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val adapter = FastItemAdapter<KP>
- val recycler = fullLinearRecycler {
-
+ val adapter = FastItemAdapter<PermissionCheckbox>()
+ setContentView(fullLinearRecycler(adapter))
+ adapter.add(listOf(
+ PERMISSION_ACCESS_COARSE_LOCATION,
+ PERMISSION_ACCESS_FINE_LOCATION
+ ).map{ PermissionCheckbox(it) })
+ adapter.withOnClickListener { _, _, item, _ ->
+ KL.d("Perm Click")
+ requestPermissions(item.permission) {
+ granted, deniedPerm ->
+ toast("${item.permission} enabled: $granted")
+ adapter.notifyAdapterDataSetChanged()
+ }
+ true
}
- setContentView(R.layout.sample)
}
override fun onBackPressed() {
startActivitySlideOut(MainActivity::class.java)
}
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ kauOnRequestPermissionsResult(permissions, grantResults)
+ }
} \ No newline at end of file
diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt
index 012d523..c1b1865 100644
--- a/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt
+++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt
@@ -4,15 +4,24 @@ import android.support.v7.widget.RecyclerView
import android.view.View
import android.widget.CheckBox
import android.widget.TextView
-import ca.allanwang.kau.iitems.KotlinIItem
+import ca.allanwang.kau.iitems.KauIItem
import ca.allanwang.kau.utils.bindView
+import ca.allanwang.kau.utils.hasPermission
/**
* Created by Allan Wang on 2017-07-03.
*/
-class PermissionCheckbox(val permission: String) : KotlinIItem<PermissionCheckbox, PermissionCheckbox.ViewHolder>(
+class PermissionCheckbox(val permission: String) : KauIItem<PermissionCheckbox, PermissionCheckbox.ViewHolder>(
R.layout.permission_checkbox, R.layout.permission_checkbox, { ViewHolder(it) }) {
+ override fun bindView(holder: ViewHolder, payloads: MutableList<Any>?) {
+ super.bindView(holder, payloads)
+ holder.text.text = permission
+ holder.checkbox.isChecked = holder.itemView.context.hasPermission(permission)
+ holder.checkbox.isClickable = false
+ holder.checkbox.jumpDrawablesToCurrentState() //Cancel the animation
+ }
+
class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
val text: TextView by bindView(R.id.perm_text)
val checkbox: CheckBox by bindView(R.id.perm_checkbox)
diff --git a/sample/src/main/res/values/styles.xml b/sample/src/main/res/values/styles.xml
index 781424d..b550607 100644
--- a/sample/src/main/res/values/styles.xml
+++ b/sample/src/main/res/values/styles.xml
@@ -7,8 +7,6 @@
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:colorBackground">#303030</item>
- <item name="android:windowShowWallpaper">true</item>
- <item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="AppTheme.NoActionBar">
@@ -16,6 +14,11 @@
<item name="windowNoTitle">true</item>
</style>
+ <style name="AppTheme.NoActionBar.Transparent">
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ </style>
+
<style name="AppTheme.Slide" parent="AppTheme">
<item name="android:windowAnimationStyle">@style/KauSlideInSlideOut</item>
</style>
diff --git a/sample/src/main/res/xml/changelog.xml b/sample/src/main/res/xml/changelog.xml
index 148e511..1fe0a61 100644
--- a/sample/src/main/res/xml/changelog.xml
+++ b/sample/src/main/res/xml/changelog.xml
@@ -9,6 +9,9 @@
<version title="v1.5"/>
<item text="Change snackbar builder" />
<item text="Change addBundle to withArguments to match ANKO" />
+ <item text="Created KauIItem to replace AbstractItem" />
+ <item text="Created permission manager and permission constants" />
+ <item text="" />
<item text="" />
<item text="" />
<item text="" />