From d024e8db464e8b0ba0133feed67896b854fd8b25 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 3 Jul 2017 22:34:05 -0700 Subject: Push permission manager for release --- .../ca/allanwang/kau/about/AboutActivityBase.kt | 2 +- .../kotlin/ca/allanwang/kau/iitems/KauIItem.kt | 23 +++++++ .../kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt | 23 ------- .../allanwang/kau/permissions/PermissionManager.kt | 7 ++- .../ca/allanwang/kau/permissions/Permissions.kt | 72 +++++++++++++++++++++- .../ca/allanwang/kau/searchview/SearchItem.kt | 5 +- .../kotlin/ca/allanwang/kau/utils/ViewUtils.kt | 5 +- 7 files changed, 103 insertions(+), 34 deletions(-) create mode 100644 library/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt delete mode 100644 library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt (limited to 'library') 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>(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/KauIItem.kt b/library/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt new file mode 100644 index 0000000..00b165c --- /dev/null +++ b/library/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt @@ -0,0 +1,23 @@ +package ca.allanwang.kau.iitems + +import android.support.annotation.LayoutRes +import android.support.v7.widget.RecyclerView +import android.view.View +import com.mikepenz.fastadapter.IClickable +import com.mikepenz.fastadapter.IItem +import com.mikepenz.fastadapter.items.AbstractItem + +/** + * Created by Allan Wang on 2017-07-03. + * + * Kotlin implementation of the [AbstractItem] to make things shorter + */ +open class KauIItem( + private val type: Int, + @param:LayoutRes private val layoutRes: Int, + private val viewHolder: (v: View) -> VH +) : AbstractItem() where Item : IItem<*, *>, Item : IClickable<*> { + override final fun getType(): Int = type + override final fun getViewHolder(v: View): VH = viewHolder(v) + override final fun getLayoutRes(): Int = layoutRes +} \ No newline at end of file diff --git a/library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt b/library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt deleted file mode 100644 index 7e4bda6..0000000 --- a/library/src/main/kotlin/ca/allanwang/kau/iitems/KotlinIItem.kt +++ /dev/null @@ -1,23 +0,0 @@ -package ca.allanwang.kau.iitems - -import android.support.annotation.LayoutRes -import android.support.v7.widget.RecyclerView -import android.view.View -import com.mikepenz.fastadapter.IClickable -import com.mikepenz.fastadapter.IItem -import com.mikepenz.fastadapter.items.AbstractItem - -/** - * Created by Allan Wang on 2017-07-03. - * - * Kotlin implementation of the [AbstractItem] to make things shorter - */ -open class KotlinIItem( - private val type: Int, - @param:LayoutRes private val layoutRes: Int, - private val viewHolder: (v: View) -> VH -) : AbstractItem() where Item : IItem<*, *>, Item : IClickable<*> { - override final fun getType(): Int = type - override final fun getViewHolder(v: View): VH = viewHolder(v) - override final fun getLayoutRes(): Int = layoutRes -} \ No newline at end of file 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> by lazy { mutableListOf>() } operator fun invoke(context: Context, permissions: Array, 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) { + @Synchronized internal fun requestPermissions(context: Context, permissions: Array) { 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, grantResults: IntArray) { + fun onRequestPermissionsResult(context: Context, permissions: Array, 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, grantResults: IntArray) +fun Activity.kauOnRequestPermissionsResult(permissions: Array, grantResults: IntArray) = PermissionManager.onRequestPermissionsResult(this, permissions, grantResults) /** @@ -23,4 +51,44 @@ fun Activity.kauOnRequestPermissionsResult(permissions: Array, 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( +) : KauIItem( 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 -- cgit v1.2.3