How to read json file from path using kotlin - android

I'm trying to open a file picker in android, select a json file then get the text from it.
The app crashes after i select the file because it can not find the path.
I have tried adding external storage read / write permission and changing the path format
/// some Activity code
val myFileIntent=Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT)
startActivityForResult(myFileIntent,10)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val path = data!!.data.path
val jsonContent = File(path).readText()
}

I'm trying to open a file picker in android
That is not a file picker. That allows the user to choose a piece of content, which may or may not be a file.
The app crashes after i select the file
You are not picking a file. You are picking a piece of content. That content is identified by a Uri, and the scheme of your Uri is content, not file.
Use ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri. You can call readText() on that InputStream to read it in as text.

This is my final working code :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val path = data?.data
val jsonSelectedFile = contentResolver.openInputStream(path);
val inputAsString = jsonSelectedFile.bufferedReader().use { it.readText() }
Toast.makeText(this, "Json: " + inputAsString , Toast.LENGTH_LONG).show()
}
And for calling :
importJsonButton.setOnClickListener {
val myFileIntent = Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT)
startActivityForResult(myFileIntent,10)
}

Related

Save a file(zip) to specify folder in Android 10

I want create a file to specify folder ,my file type is zip,I want use
FileOutStream to create.
It sends an intent, you can see the code below:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(mContext,intent, 9999,null)
then it gets the returned data, you can see the code below:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
when (requestCode) {
9999 -> {
Log.v("Test", "Result URI " + data!!.getData())
// FileInputStream(data!!.getData())
}
}
}
}
}
the log is
V/Test: Result URI content://com.android.externalstorage.documents/tree/primary%3ATestFile
I want to create file with the Uri,but use FileOutStream will crash,have any way to create file in specify folder?

I can't delete the folder's content from path

I'm currently getting this path from my FileExplorer
val path = "content://com.android.externalstorage.documents/tree/primary:Download"
And I'm trying to delete the content of this location:
val fileFolder = File(path)
deleteFolderContent(fileFolder)
private fun deleteFolderContent(fileFolder: File) {
val files = fileFolder.listFiles()
if (files.isNullOrEmpty()) {
return
} else {
for (file in files) {
file.delete()
}
}
}
But files is always null and I can't delete the content. What am I doing wrong? Can anyone help me? Thanks.
Update:
For obtain this "path" I did this:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, SELECT_FOLDER_REQUEST_CODE)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SELECT_FOLDER_REQUEST_CODE && resultCode == RESULT_OK) {
val uriTree = data?.data
}
}
you can't access content directory as a File (even when URI points on local storage). check out Providers and ContentResolver, HERE you have some basics, for files there is special one: FileProvider. but for your case ContentResolver may fit for your needs best, with method:
context.contentResolver.delete(uriToDelete, null, null)

Can't set image URI because Permission Denial: opening provider

Good afternon,
I crate an app with Room database to save items (name, desc, price, image). I have 3 activities. The 1st activity for create, the 2nd MainActivity with RecyclerView and the last activity (ChangeActivity) open when I click on item in MainActivity. When I create an item I pick image and save uri in database. I want to set image in ImageView in ChangeActivity but get
Unable to start activity ComponentInfo {hop.test.aah/hop.test.aah.ChangeActivity}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{7a3e034 25078:hop.test.aah/u0a95} (pid=25078, uid=10095) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs.
I tried some solutions what I found but nothing help or maybe I wrong and it is why I ask some help.
ChangeActivity:
In manifest I only add READ_EXTERNAL_PERMISSION and WRITE_EXTERNAL PERMISSION.
This is how I pick image:
UPD 2:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val resolver = applicationContext.contentResolver
val flags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
resolver.takePersistableUriPermission(image!!, flags)
and fun to get
#Throws(IOException::class)
fun getBitmapFromUri(uri: Uri): Bitmap {
val parcelFileDescriptor: ParcelFileDescriptor? =
contentResolver.openFileDescriptor(uri, "r")
val fileDescriptor: FileDescriptor = parcelFileDescriptor!!.fileDescriptor
val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
parcelFileDescriptor.close()
return image
}
This works for me:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/jpeg"
startActivityForResult(
Intent.createChooser(
intent,
getString(R.string.chooser_title)
), RC_GALLERY)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
if (requestCode == RC_GALLERY) {
imgUri = data?.data
val contentResolver = applicationContext.contentResolver
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
imgUri?.let { contentResolver.takePersistableUriPermission(it, takeFlags) }
}
}
}
Step #1: Switch to ACTION_OPEN_DOCUMENT.
Step #2: In onActivityResult(), when you get the Uri, call takePersistableUriPermission() on a ContentResolver
Then, and only then, will you be able to save the Uri in a database and use it to access content in the future.
With your current approach, the Uri works for the activity that receives the onActivityResult() call, but it will not work for future processes.

How to open a file explorer and get selected file path using implicit intent kotlin

I want to open a file explorer and get selected file path in Kotlin Is there any guid for this purpose?
The most simple option to show a file explorer is to call to the "ACTION_GET_CONTENT" intent and get a code result (777 at the example) with "startActivityForResult", like this:
val intent = Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT)
startActivityForResult(Intent.createChooser(intent, "Select a file"), 777)
Later, override the "onActivityResult" function in your activity and get the data only if the request code is the same that the "startActivityForResult" (777 at the example).
To save the URI from the selected file you can get "data?.data.toString()" and if you only need the path, use "data?.data?.path"
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 777) {
val filePath = data?.data?.path
}
}

ZipFile Kotlin class returns java.io.FileNotFoundException: File doesn't exist

I'm learning how to work with zip files in Kotlin. In theory my app should read files from zip and extract them if needed. For this task I use java.util.zip.ZipFile, but when I pass a file I choose, the app crashes, saying the file doesn't exist.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT)
startActivityForResult(Intent.createChooser(intent, "Select a file"), 111)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 111 && resultCode == RESULT_OK) {
val selectedFile = data?.data
var file = File(selectedFile!!.path)
var zipFile = ZipFile(file)
}
}
java.io.FileNotFoundException: File doesn't exist: /document/acc=1;doc=155
ZipFile only works with files, while the result of ACTION_GET_CONTENT is an Uri, from which you can usually not get a file (see How to Consume Content From a Uri for a detailed explanation).
There are two solutions :
Use a ZipInputStream, which can extract the content of a stream.
Copy the stream from the Uri to a local file, then open it with the ZipFile

Categories

Resources