我需要将图像保存到/sdcard/sample/0/b/image.png。我尝试过:
val dir = File("/sdcard/sample/0/b/")
dir.mkdirs()
val image = File(dir, "image.png")
image.createNewFile()
var out: FileOutputStream? = null
try {
out = FileOutputStream(image)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)
} finally {
out?.close()
}
我总是收到那个文件不存在。另外,我尝试用Environment.getExternalStorageDirectory()。path替换“ / sdcard”,但结果是相同的。
java.io.IOException: No such file or directory
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:281)
at java.io.File.createNewFile(File.java:1000)
在清单中,为了进行测试,我添加了
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission-sdk-23 android:name="android.permission.READ_EXTERNAL_STORAGE"/>
答案 0 :(得分:0)
我应该使用
val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
requestPermissions(permissions, 0x512)
即使我添加了权限来显示sdk-23
<uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
答案 1 :(得分:0)
尝试使用:
val dir = File(Environment.getExternalStorageDirectory().absolutePath + "/b/")
如果没有SDCard,则将返回“ / storage / emulated / 0”或类似的值,具体取决于手机型号和android版本。 还请求权限。
答案 2 :(得分:0)
此答案将很长,但是可以解决,并且奖金代码包含所有步骤,该代码显示了如何优雅地管理权限。 OH要谦虚
首先,这段代码是用Kotlin编写的
为了清楚起见,您需要将此文件包含在清单文件文件夹中
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我们将使用在Model数据类中声明的几个全局变量
companion object { var THE_PATH = "";var gv = 3 }
我们的LAUNCHER活动名为CheckStorageActivity,这是长代码
此活动检查用户是否有SD卡,然后根据检查结果向用户显示内部或外部存储对话框
在这种情况发生之前,尽管用户需要管理授予权限
警告中的重要提示:在真实设备上测试此代码,请参见代码中的注释
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"