这个答案会很长,但它可以工作,并且所有步骤都包含在 BONUS CODE 中,该代码显示了如何优雅地管理权限。哦,要谦虚
首先这段代码是用 Kotlin 编写的
为清楚起见,您需要将其包含在您的清单文件夹中
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我们将使用在模型数据类中声明的几个全局变量
companion object { var THE_PATH = "";var gv = 3 }
我们的 LAUNCHER Activity 被命名为 CheckStorageActivity 这里是长代码
此活动检查用户是否有 SD 卡,然后根据检查结果向用户显示内部或外部存储对话框
在任何这种情况发生之前,尽管用户需要管理授予权限
注意事项在真实设备上测试此代码,查看代码中的 cmets
class CheckStorageActivity : AppCompatActivity() {
private val STORAGE_PERMISSION_CODE = 1
var STORAGE_LOCATION: Int = 3
var the_path = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_check_storage)
supportActionBar?.hide()
val preferences = getSharedPreferences("FirstPreference", Context.MODE_PRIVATE)
if (!preferences.getBoolean("isFirstTime", false)) {
val sharedPreferences = getSharedPreferences("SecondPref", Context.MODE_PRIVATE)
val editorshared = sharedPreferences.edit()
editorshared.putString("DB_PATH", THE_PATH)
editorshared.apply()
val pref = getSharedPreferences("FirstPreference", Context.MODE_PRIVATE)
val editor = pref.edit()
editor.putBoolean("isFirstTime", true)
editor.apply()
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// this only runs on re START APP 1
val sharedPreferences = getSharedPreferences("SecondPref", Context.MODE_PRIVATE)
the_path = sharedPreferences.getString("DB_PATH", "")
if(the_path != ""){
pathONLY()
}
//showIMAGE()?
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestStoragePermission()
}
}// end onCreate
fun pathALL(){
val sharedPreferences = getSharedPreferences("SecondPref", Context.MODE_PRIVATE)
the_path = sharedPreferences.getString("DB_PATH", "")
val fi = File("storage/")
val lst = fi.listFiles()
val top = lst[1].toString()
val bot = lst[0].toString()
println("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT top $top")
// TOP VALUE ON EMULATOR storage/self
// THIS MUST BE USED ON emulator to test
// For real device use storage/emulated for top String variable
// =============================================================
println("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB bot $bot")
// BOT VALUE ON EMULATOR storage/emulated
// Do not use on Emulator it will NOT work
if (top.contains("storage/self")) {
STORAGE_LOCATION = 0
internalDIALOG()
}
if (bot.contains("-")) {
STORAGE_LOCATION = 1
externalDIALOG()
}
}
fun pathONLY(){
val sharedPreferences = getSharedPreferences("SecondPref", Context.MODE_PRIVATE)
the_path = sharedPreferences.getString("DB_PATH", "")
THE_PATH = the_path
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
fun writeSharedPrefANDleave(){
val sharedPreferences = getSharedPreferences("SecondPref", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putString("DB_PATH", THE_PATH)
editor.apply()
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
fun internalDIALOG() {
val builder = AlertDialog.Builder(this)
builder.setCancelable(false)
builder.setTitle("SD Card NOT Mounted")
builder.setMessage("\nClick OK to use INTERNAL Device Storage")
builder.setNeutralButton("OK") { dialogInterface, i ->
STORAGE_LOCATION == 0
setThePath()
writeSharedPrefANDleave()
}
builder.show()
}
fun externalDIALOG() {
val builder = AlertDialog.Builder(this)
builder.setCancelable(false)
builder.setTitle("Select Data Storage Location ")
builder.setMessage("EXTERNAL Use SD CARD\n\n" + "INTERNAL Device Storage")
builder.setPositiveButton("EXTERNAL") { dialogInterface, i ->
STORAGE_LOCATION = 1
setThePath()
writeSharedPrefANDleave()
}
builder.setNegativeButton("INTERNAL") { dialogInterface, i ->
STORAGE_LOCATION = 0
setThePath()
writeSharedPrefANDleave()
}
builder.show()
}
fun setThePath(): String {
val removable = ContextCompat.getExternalFilesDirs(this, null)[STORAGE_LOCATION]
if (STORAGE_LOCATION == 1) {
THE_PATH = removable.toString()
THE_PATH = THE_PATH + "/Documents/"
}
if (STORAGE_LOCATION == 0) {
THE_PATH = removable.toString()
THE_PATH = THE_PATH + "/INTERNAL/"
}
return THE_PATH.trim()
}
companion object {var MANUALLY_SET = 1}
// Manage Navigation if Permission Manually Set
override fun onResume() {
super.onResume()
if(MANUALLY_SET == 2){
pathALL()
}
}
private fun requestStoragePermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
AlertDialog.Builder(this)
.setTitle("To Write to DB Allow Permissions")
.setMessage("On the Next Screen to Remove the App\n\nCheck Don't Ask Again and Click DENY\n\nOr Click ALLOW to Grant Permission")
.setPositiveButton("NEXT") { dialog, id ->
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), STORAGE_PERMISSION_CODE)
}
.create().show()
} else {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), STORAGE_PERMISSION_CODE)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == STORAGE_PERMISSION_CODE) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(gv == 3){
pathALL()
}
//showIMAGE()
} else {
if (Build.VERSION.SDK_INT >= 23 && !shouldShowRequestPermissionRationale(permissions[0])) {
val alertDialogBuilder = AlertDialog.Builder(this)
alertDialogBuilder.setTitle("Set Permissions or UN-Install App")
alertDialogBuilder
.setMessage("Click SETTINGS to Manually Set\n\n"+"OR to UN-Install the Application")
.setCancelable(false)
.setPositiveButton("SETTINGS") { dialog, id ->
MANUALLY_SET = 2
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivityForResult(intent, 1000)
}
val alertDialog = alertDialogBuilder.create()
alertDialog.show()
} else run {
// User selected Deny Dialog to EXIT App ==> OR <== RETRY to have a second chance to Allow Permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
val alertDialogBuilder = AlertDialog.Builder(this)
alertDialogBuilder.setTitle("RETRY")
alertDialogBuilder
.setMessage("Click RETRY to Set Permissions\n\n"+"Permissions MUST be set to Enter Data")
.setCancelable(false)
.setPositiveButton("RETRY") { dialog, id ->
dialog.cancel()
val intent = Intent(this, CheckStorageActivity::class.java)
startActivity(intent)
}
val alertDialog = alertDialogBuilder.create()
alertDialog.show()
}
}
}
}
}
}
现在在您的 DBHelper 类中,您可以在其中执行所有 CRUD 并使用此格式创建数据库
import com.androidstackoverflow.kotlinsqlite.Note.Companion.THE_PATH
和
class NoteDbManager(context: Context) {
private val dbName = THE_PATH +"JSANotes.db"
private val dbTable = "Notes"