在多个文件中拆分运行时权限

时间:2018-03-23 21:36:57

标签: android kotlin

我在Android中使用以下代码授予run time permission,此处我正在尝试为Camera执行此操作。

我将所需要的内容添加到最清晰的内容中:

<uses-permission android:name="android.permission.CAMERA"/>

以下MainActivity.Kt与我完美配合:

package com.example.hasan.runtime.feature

import android.Manifest
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.widget.Toast
import feature.utilis.isPermissionGranted
import feature.utilis.requestPermission
import feature.utilis.shouldShowPermissionRationale
import feature.utilis.showSnackbar
import kotlinx.android.synthetic.main.activity_main.*

const val PERMISSION_REQUEST_CAMERA = 0

class MainActivity : AppCompatActivity() {

  //  private lateinit var layout: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn_cam.setOnClickListener { showCamera() }
    }

    fun showCamera() {
        if (isPermissionGranted(Manifest.permission.CAMERA)) {
            main_layout.showSnackbar(R.string.camera_permission_available,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok){
                startCamera()
            }
        } else {
            requestCameraPermission()
        }
    }

    fun startCamera() {
        // val intent = Intent(this, CameraPreviewActivity::class.java)
        // startActivity(intent)

        Toast.makeText(this, "Done correctly", Toast.LENGTH_LONG).show()

    }

    private fun requestCameraPermission() {
        // Permission has not been granted and must be requested.
       if (shouldShowPermissionRationale(Manifest.permission.CAMERA)) {
            main_layout.showSnackbar(R.string.camera_access_required,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok) {
                requestPermission(Manifest.permission.CAMERA,
                        PERMISSION_REQUEST_CAMERA)
            }
        } else {
            main_layout.showSnackbar(R.string.camera_permission_not_available,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok){}
       }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
                                            grantResults: IntArray) {
        if (requestCode == REQUEST_CAMERA) {
            if (isPermissionGranted(Manifest.permission.CAMERA)) {
                main_layout.showSnackbar(R.string.camera_permission_available,
                        Snackbar.LENGTH_INDEFINITE, R.string.ok){}
            } else {
                main_layout.showSnackbar(R.string.camera_permission_not_available,
                        Snackbar.LENGTH_INDEFINITE, R.string.ok){}

            }
        } else if (requestCode == REQUEST_CONTACTS) {


        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    companion object {
        const val REQUEST_CAMERA = 0
        const val REQUEST_CONTACTS = 1
        val PERMISSIONS_CONTACT = arrayOf(Manifest.permission.READ_CONTACTS,
                Manifest.permission.WRITE_CONTACTS)
    }
}

我在下面Extensions写了这些内容,只是为了让上面的代码非常清楚谁阅读它:

ActivityExt.Kt

package feature.utilis

import android.content.pm.PackageManager
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AppCompatActivity

fun AppCompatActivity.isPermissionGranted(permission: String) =
        ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED

fun AppCompatActivity.shouldShowPermissionRationale(permission: String) =
        ActivityCompat.shouldShowRequestPermissionRationale(this, permission)

fun AppCompatActivity.requestPermission(permission: String, requestId: Int) =
        ActivityCompat.requestPermissions(this, arrayOf(permission), requestId)

fun AppCompatActivity.batchRequestPermissions(permissions: Array<String>, requestId: Int) =
        ActivityCompat.requestPermissions(this, permissions, requestId)

ViewExt.Kt

package feature.utilis

import android.support.design.widget.Snackbar
import android.view.View

fun View.showSnackbar(msgId: Int, length: Int) {
    showSnackbar(context.getString(msgId), length)
}

fun View.showSnackbar(msg: String, length: Int) {
    showSnackbar(msg, length, null, {})
}

fun View.showSnackbar(
        msgId: Int,
        length: Int,
        actionMessageId: Int,
        action: (View) -> Unit
) {
    showSnackbar(context.getString(msgId), length, context.getString(actionMessageId), action)
}

fun View.showSnackbar(
        msg: String,
        length: Int,
        actionMessage: CharSequence?,
        action: (View) -> Unit
) {
    val snackbar = Snackbar.make(this, msg, length)
    if (actionMessage != null) {
        snackbar.setAction(actionMessage) {
            action(this)
        }.show()
    }
}

我的问题是,当我添加我需要的所有权限时,我觉得MainActivity.Kt文件会非常长,因为建议逐个询问它们,如何将其拆分为多个文件,以便每个文件都执行该操作权限所需的操作,例如SMSContact,...

1 个答案:

答案 0 :(得分:0)

我通过以下方式解决了这个问题:

创建ActivityExt.tk

package feature.extensions

import android.app.Activity
import android.content.pm.PackageManager
import android.support.v4.app.ActivityCompat
import android.widget.Toast

fun Activity.isPermissionGranted(permission: String) =
        ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED

fun Activity.arePermissionsGranted(permissions: Array<String>): Boolean {
    permissions.forEach { it ->
        if(ActivityCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED)
            return false
    }
    return true
}

fun Activity.shouldShowPermissionRationale(permission: String) =
        ActivityCompat.shouldShowRequestPermissionRationale(this, permission)

fun Activity.requestPermission(permission: String, requestId: Int) =
        ActivityCompat.requestPermissions(this, arrayOf(permission), requestId)

fun Activity.batchRequestPermissions(permissions: Array<String>, requestId: Int) =
        ActivityCompat.requestPermissions(this, permissions, requestId)


fun Activity.toast(message: CharSequence) =
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()

创建PermissionsResult.Kt

package feature.utilities

import android.Manifest
import android.Manifest.permission.*
import android.app.Activity
import android.support.design.widget.Snackbar
import android.view.View
import com.example.hasan.runtime.feature.PERMISSION_REQUEST_CAMERA
import com.example.hasan.runtime.feature.R
import feature.extensions.requestPermission
import feature.extensions.toast
import feature.extentions.showSnackbar

object UtilPermissionsResult {
    fun getPermissionsResult(activity: Activity?, layout: View?,
                             permissions: Array<String>, grantResults: IntArray) {

        val permissionsMap = HashMap<String, Int>()
        for ((index, permission) in permissions.withIndex()) {
            permissionsMap[permission] = grantResults[index]
        }

        if(permissionsMap[CAMERA] != 0) {
            layout!!.showSnackbar(R.string.camera_permission_not_available,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok){
                activity!!.toast("Camera permission NOT granted")
                activity!!.requestPermission(Manifest.permission.CAMERA,
                        PERMISSION_REQUEST_CAMERA)
            }
        }
        else {
            layout!!.showSnackbar(R.string.camera_permission_available,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok){
                activity!!.toast("Camera permission granted")
            }
        }

        if(permissionsMap[ACCESS_FINE_LOCATION] != 0
                || permissionsMap[READ_SMS] != 0) {
                activity!!.toast("Location and permissions are a must")
            } else {
                activity!!.toast("Thanks, all permissions had been granted")
        }
    }
}

创建Permissions.Kt

package feature.utilities

import android.Manifest.permission.*
import android.app.Activity
import android.support.design.widget.Snackbar
import android.view.View
import com.example.hasan.runtime.feature.PERMISSION_REQUEST_ALL
import com.example.hasan.runtime.feature.PERMISSION_REQUEST_CAMERA
import com.example.hasan.runtime.feature.R
import feature.extensions.*
import feature.extentions.showSnackbar

val PERMISSIONS =
        arrayOf(ACCESS_FINE_LOCATION,
                ACCESS_COARSE_LOCATION,
                READ_SMS, READ_CONTACTS,
                ACCESS_NETWORK_STATE)

object UtilPermissions {
    fun showCamera(activity: Activity?, layout: View?) {
     //   using context
        if (activity!!.isPermissionGranted(CAMERA)) {
                startCamera(activity)
        } else {
            requestCameraPermission(activity, layout)
        }
    }

    private fun requestCameraPermission(activity: Activity?, layout: View?) {
        if (activity!!.shouldShowPermissionRationale(CAMERA)) {
            layout!!.showSnackbar(R.string.camera_access_required,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok) {
                // activity!!.requestPermission(CAMERA, PERMISSION_REQUEST_CAMERA)
                 activity!!.batchRequestPermissions(PERMISSIONS, PERMISSION_REQUEST_ALL)
            }
        }
        else {  // useful in case camera not available
            layout!!.showSnackbar(R.string.camera_permission_not_available,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok){
                activity!!.requestPermission(CAMERA,
                        PERMISSION_REQUEST_CAMERA)
            }
        }
    }

private fun startCamera(activity: Activity?) {
        // val intent = Intent(this, CameraPreviewActivity::class.java)
        // startActivity(intent)

        activity!!.toast("Done smoothly")

    }   
}

然后MainActivity.Kt变得像下面一样简单和小:

package com.example.hasan.runtime.feature

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import feature.utilities.UtilPermissions.showCamera
import feature.utilities.UtilPermissionsResult.getPermissionsResult
import kotlinx.android.synthetic.main.activity_main.*

const val PERMISSION_REQUEST_CAMERA = 0
const val PERMISSION_REQUEST_ALL = 0

private lateinit var layout: View

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        layout = main_layout
        btn_cam.setOnClickListener { showCamera(this, main_layout) }

    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
                                            grantResults: IntArray) {
        getPermissionsResult(
                this,
                layout,
                permissions,
                grantResults
        )
    }
}

AndroidManifest.xml包括以下内容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hasan.runtime.feature">

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <application>
        <activity android:name=".MainActivity">
            <intent-filter android:order="1">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="example.com"
                    android:pathPattern="/.*"
                    android:scheme="https" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我的ViewWxt.Kt仍然没有变化:

package feature.extentions

import android.support.design.widget.Snackbar
import android.view.View

fun View.showSnackbar(msgId: Int, length: Int) {
    showSnackbar(context.getString(msgId), length)
}

fun View.showSnackbar(msg: String, length: Int) {
    showSnackbar(msg, length, null, {})
}

fun View.showSnackbar(
        msgId: Int,
        length: Int,
        actionMessageId: Int,
        action: (View) -> Unit
) {
    showSnackbar(context.getString(msgId), length, context.getString(actionMessageId), action)
}

fun View.showSnackbar(
        msg: String,
        length: Int,
        actionMessage: CharSequence?,
        action: (View) -> Unit
) {
    val snackbar = Snackbar.make(this, msg, length)
    if (actionMessage != null) {
        snackbar.setAction(actionMessage) {
            action(this)
        }.show()
    }
}

我为'getLocation.Kt'创建了另一个文件,并且使用以下代码运行正常:

package feature.utilities

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.location.Location
import android.support.design.widget.Snackbar
import android.view.View
import android.widget.TextView
import com.example.hasan.runtime.feature.PERMISSION_REQUEST_ALL
import com.example.hasan.runtime.feature.R
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import feature.extensions.arePermissionsGranted
import feature.extensions.batchRequestPermissions
import feature.extensions.toast
import feature.extentions.showSnackbar

val PERMISSIONS =
        arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION)

private lateinit var fusedLocationClient: FusedLocationProviderClient

object UtilLocation {
    fun getLocation(activity: Activity?, layout: View?, latitudeTxt: TextView?, longitudeTxt: TextView?) {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(activity!!)

        if (activity!!.arePermissionsGranted(PERMISSIONS)) {
                startLocation(activity, layout, latitudeTxt, longitudeTxt)
        } else {
                requestCameraPermission(activity, layout)
        }
    }

    private fun requestCameraPermission(activity: Activity?, layout: View?) {
            layout!!.showSnackbar(R.string.location_access_required,
                    Snackbar.LENGTH_INDEFINITE, R.string.ok) {
                activity!!.batchRequestPermissions(PERMISSIONS, PERMISSION_REQUEST_ALL)
            }
    }

    @SuppressLint("MissingPermission")
    private fun startLocation(activity: Activity?, layout: View?, latitudeTxt: TextView?, longitudeTxt: TextView?) {

        fusedLocationClient.lastLocation
                .addOnSuccessListener { location : Location? ->
                    latitudeTxt!!.text = location!!.latitude.toString()
                    longitudeTxt!!.text = location!!.longitude.toString()
                    // Got last known location. In some rare situations this can be null.
                    activity!!.toast("lat: "+location!!.latitude.toString()+", long: "+location!!.longitude.toString())
                }
    }
}