Permissions
Android applications are isolated from the operating system. Because of this they need to request permission to perform and accesss certain operations and actions.
Andriod Manifest
Defines the permissions needed
<manifest xmlns:android=
"http://schemas.android.com/apk/res/android"
package="com.journaler">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name=
"android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name=
"android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name=
"android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name=
"android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name=
"android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name=
"android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<application ... >
...
</application
...
</manifest>
Runtime Permissions
Some permissions have to be requested at Runtime, with the ActivityCompat.requestPermissions
method. The results are available in the onRequestPermissionsResult
method.
abstract class BaseActivity : AppCompatActivity() {
companion object {
val REQUEST_GPS = 0
... }
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
requestGpsPermissions() }
...
private fun requestGpsPermissions() {
ActivityCompat.requestPermissions(
this@BaseActivity,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION ),
REQUEST_GPS ) }
...
override fun onRequestPermissionsResult(
requestCode:
Int, permissions: Array<String>, grantResults: IntArray ) {
if (requestCode == REQUEST_GPS) {
for (grantResult in grantResults)
{ if (grantResult == PackageManager.PERMISSION_GRANTED)
{ Log.i( tag, String.format( Locale.ENGLISH, "Permission
granted [ %d ]", requestCode ) )
}
else {
Log.e( tag, String.format( Locale.ENGLISH, "Permission
not granted [ %d ]", requestCode ) )
} } } } }
Kotlin simplifications
interface PermissionRequestCallback {
fun onPermissionGranted(permissions: List<String>)
fun onPermissionDenied(permissions: List<String>)
}
abstract class PermissionCompatActivity : AppCompatActivity() {
private val tag = "Permissions extension"
private val latestPermissionRequest = AtomicInteger()
private val permissionRequests = ConcurrentHashMap<Int,
List<String>>()
private val permissionCallbacks =
ConcurrentHashMap<List<String>, PermissionRequestCallback>()
private val defaultPermissionCallback = object :
PermissionRequestCallback {
override fun onPermissionGranted(permissions: List<String>) {
Log.i(tag, "Permission granted [ $permissions ]")
}
override fun onPermissionDenied(permissions: List<String>) {
Log.e(tag, "Permission denied [ $permissions ]")
}
}
fun requestPermissions(
vararg permissions: String,
callback: PermissionRequestCallback = defaultPermissionCallback
) {
val id = latestPermissionRequest.incrementAndGet()
val items = mutableListOf<String>()
items.addAll(permissions)
permissionRequests[id] = items
permissionCallbacks[items] = callback
ActivityCompat.requestPermissions(this, permissions, id)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
val items = permissionRequests[requestCode]
items?.let {
val callback = permissionCallbacks[items]
callback?.let {
var success = true
for (x in 0..grantResults.lastIndex) {
val result = grantResults[x]
if (result != PackageManager.PERMISSION_GRANTED) {
success = false
break
}
}
if (success) {
callback.onPermissionGranted(items)
} else {
callback.onPermissionDenied(items)
}
}
}
}
}
use
abstract class BaseActivity : PermissionCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
...
requestPermissions(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
}
...
}