Intent.FLAG_GRANT_READ_URI_PERMISSION flag usage - android

I'm facing with the following problem:
I created application where user can keep his own private files and I need to pass these files to default viewers (PDFViewer for example).
The problem is that files are private and PDFViewer has no access to my files. I solved this issue using approach that is used in email clients - I created content provider where I return ParcelFileDescriptor.
Now it works great, but I faced with new problem - documentation says I need to use Intent.FLAG_GRANT_READ_URI_PERMISSION flag when I pass URI to PDFViewer, but in my case it works well even without this flag and even with "android:grantUriPermissions="false""
Looks like now my files become not private because of content provider.
How to make it honor Intent.FLAG_GRANT_READ_URI_PERMISSION flag?

Found the problem - I forgot to add "android:readPermission" flag to my provider

Related

How can I make my Android app read and write a .txt file?

I'm using Xamarin, C# and Monogame and I'm taking a fully-working Desktop game and porting it over to Android.
My problem is that I have this "Content folder" that you would always use in the Desktop version of the app. But I cannot access it or any other folder through the code directly using Android.
basicShader = new Effect(game1.GraphicsDevice,System.IO.File.ReadAllBytes("Content/TextureShader.mgfxo"));
This works just fine in the Desktop app but throws System.IO.DirectoryNotFoundException:'Could not find a part of the path "/Content/TextureShader.mgfxo".' on Android.
I'd like to mention that I already had the code and the project working perfectly when it was a desktop program. I also have a private class-level variable string[] list_of_files and in the constructor, I had the line list_of_files = Directory.GetFiles("./Content","*.txt");
This is for saving and loading player data. It may have been rudimentary but I had a fully functioning program that saved and loaded data on my computer. I am transitioning this program to be an Android app and this is the only part of the project that isn't working. When I run the code as it was originally written, I get "System.IO.DirectoryNotFoundException: 'Could not find a part of the path '/Content'.' ".
I've tried playing around with trying to read the contents of different folders.
I've messed around with different paths, including the Resources folder instead.
I added <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to my manifest.
I know that I'm trying to access internal storage, not external, so I also tried <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" /> just to see if that might work.
Nothing works.
In another stack overflow post, a guy commented:
For the people who are facing NullPointerException - you are trying to access the files in the app's internal storage which are private sorry you can't do that. –
coderpc
Jun 23, 2017 at 16:00
I cannot imagine why this would be true. Why would a programmer not be able to write a program that can access it's own internal storage? That makes no sense to me. Obviously my app needs to be able to read and write it's own internal storage! And if this is true, then how else can I save persistent data on my phone? I don't want a database or a shared thingamabobber that uses key-value pairs, I have a self-made system that works as a text file and I want to continue to use it. I refuse to believe that an Android app can't keep track of a simple .txt file in one of it's own folders, that's just too hard for me to imagine. It can't be true.
I wanted to ask the commenter about his comment but Stack Overflow wouldn't let me because I don't have over 50xp.
Just like CommonsWare sayed, you can use the Intent.ActionOpenDocument to get the uri of the file. Such as
static readonly int READ_REQUEST_CODE = 1337;
Intent intent = new Intent(Intent.ActionOpenDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.SetType("*/*");
StartActivityForResult(intent, READ_REQUEST_CODE);
And override the OnActivityResult method:
if (requestCode == READ_REQUEST_CODE && resultCode == Result.Ok)
{
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter. Pull that uri using "resultData.getData()"
if (data != null)
{
Android.Net.Uri uri = data.Data;
DocumentFile documentFile = DocumentFile.FromSingleUri(this.ApplicationContext,uri);
// Then you can operate the file with input and output stream
}
}
More information please check the simple on the github:
https://github.com/xamarin/monodroid-samples/blob/main/StorageClient/StorageClientFragment.cs
In addition, if you can ensure the file's path. You can use the StreamWriter and the StreamReader to write and read the file. Such as:
using (StreamWriter sw = new StreamWriter(path))
{
sw.WriteLine(content);
}
Furthermore, you can try to create the content folder and the txt file in the Android with the following code.
var filename1 = Android.App.Application.Context.GetExternalFilesDir(System.DateTime.Now.ToString("Content")).AbsolutePath;
var filename = System.IO.Path.Combine(filename1, "xxx.txt");
using (System.IO.FileStream os = new System.IO.FileStream(filename, System.IO.FileMode.Create))
{
}
The folder and the files created by this way belongs to the app and you can access it easily.
You can read the official document about the storage in the Android.
Link : https://developer.android.com/training/data-storage/shared/documents-files

How to change the osmdroid default path to extSdCard?

I would like to know, how to change the osmdroid default path to an extSdCard path?
according to the documentation, it is possible using:
Configuration.getInstance().SetOsmdroidBasePath();
I believe when running my project it automatically starts on the way:
StorageUtils.getStorage().GetAbsolutePath() , "osmdroid"
I tried to use the command below, but my map does not display the tiles
Configuration.getInstance().setOsmdroidBasePath(new File("/mnt/extSdCard/osmdroid"));
And when I debug my code using this: Configuration.getInstance().GetOsmdroidBasePath().GetPath()
It presents the correct path.
It is necessary to perform some reload of my map?
If the user has granted runtime permissions for storage before the map view is created, then it should work just fine. You may want to check to make sure you can write to that path. Android is strange and often times just because a path is available does not mean you can write to it. The StorageUtils class can help you find the available paths and it should be able to determine which path is writable. It is, however, imperfect. Paths can vary from device to device and results can be unpredictable.looking at this link might help you.
For OSM version 6.x you can use the following code
#Override
public void onCreate() {
...
org.osmdroid.config.IConfigurationProvider osmConf = org.osmdroid.config.Configuration.getInstance();
File basePath = new File(getCacheDir().getAbsolutePath(), "osmdroid");
osmConf.setOsmdroidBasePath(basePath);
File tileCache = new File(osmConf.getOsmdroidBasePath().getAbsolutePath(), "tile");
osmConf.setOsmdroidTileCache(tileCache);
...
}

Open an Image in Internal Storage Using Content Provider

Let's say I package an image with my app and I want to open it with the default image viewer/whatever image viewer the user has chosen to be the default. How would I do that?
There's already this post: Open an image using URI in Android's default gallery image viewer but many of the answers are obsolete because due to the introduction of android N, a content provider must be used.
The only answer I can find is this one:
File file = ...;
final Intent intent = new Intent(Intent.ACTION_VIEW)//
.setDataAndType(VERSION.SDK_INT >= VERSION_CODES.N ?
android.support.v4.content.FileProvider.getUriForFile(this,getPackageName() + ".provider", file) : Uri.fromFile(file),
"image/*").addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
but, according to the author of this solution, this code only works for images stored externally, not ones that may be packaged with my app.
You won't be able to open an image packaged with the app (in drawable or whatever resources) through an external application. You should first copy it into (at least) an internal file storage. After that you can implement a FileProvider to provide access to this file.
Let me know if you need more details on this. Hope it helped.

What's the difference between File.toURI vs Uri.fromFile in Android

While trying to get a picture using a Camera intent as describe in the documentation.
I've added the required MediaStore.EXTRA_OUTPUT extra but the problem was that it didn't save the file where I wanted. So I read the documentation more carefully, and compared it with what I was doing (since I didn't blindly copy/pasted the provided sample code), and found that I was using
intent.putExtra(MediaStore.EXTRA_OUTPUT, myFile.toURI());
Instead of
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(myFile));
The second version worked perfectly, but I can't figure out why. The documentation for both methods don't state anything related to incompatibility between the two.
Shouldn't the two give the same result, or am I missing a subtle difference?
Just from a quick test here:
Uri.fromFile() returns a Uri (android.net.Uri)
file.toURI() returns a URI (java.net.URI)
I expect this is causing the problem.
The content produced by Uri.fromFile() and file.toURI() is not the same...
for the same file "f" located on the sdcard.
"f.toURI()" will add this into your Bundle {output=file:/mnt/sdcard/Gp/Gp.db}
and "Uri.fromFile(f)" will add {output=file:///mnt/sdcard/Gp/Gp.db}

Not a DRM File, opening notmally

I am looking for a solution regarding a repeating log print that is caused by calling
BitmapFactory.decodeFile.
In My app i have a ListView that is being redrawn by a timer every second.
The ListView has an ImageView that gets is image source from the local storage, (not from the network)
The image is stored in :
filePath = /data/data/com.xxx.testlib/files/b22a1a294fd6e5ad3ea3d25b63c4c735.jpg
I am using the following code to redraw the image and it is working fine. with out exception.
try
{
File filePath = context.getFileStreamPath(imageName);
if(filePath.exists()){
bMap = BitmapFactory.decodeFile(filePath.getPath());
}
}catch (Exception e)
{
e.printStackTrace();
}
But when preforming the following line :
bMap = BitmapFactory.decodeFile(filePath.getPath());
I get a print in the log as follow:
03-07 09:55:29.100: I/System.out(32663): Not a DRM File, opening notmally
03-07 09:55:29.105: I/System.out(32663): buffer returned
....
How can i get read from the printing to the log.
Thank you
lior
Edit
Also it lags the phone whenever this operation is performed. And this reduced performance is noticeable specially when the phone is Waked up and we return to activity with this code.
Its more than a year for OP and still no answer is found. If anyone has found solution then please post it.
Thank you.
DRM stands for Digital Rights Management. It's normally a special keys used by owners of content to make sure that your device is authorized to view/play the content. iTunes was notorious for this for ages.
All it's doing is letting you know that the material you are opening is not DRM protected, and therefore can be opened normally.
Hope, this might help you.
I also got the same exception when i tried to save the image captured by camera directly to : /data/data/com.xxx.testlib/images/b22a1a294fd6e5ad3ea3d25b63c4c735.jpg.
Then i first saved the image to default location used by camera and the copied it to : /data/data/com.xxx.testlib/images/b22a1a294fd6e5ad3ea3d25b63c4c735.jpg.
and now "Not a DRM File, opening notmally" is removed from the log and saved the image successfully.
Conclussion : folder :- "/data/data/com.xxx.testlib/" is private and can be accessible from inside the application only.
Maybe it's a permission error.
Do you have added the right permission in your Manifest ?
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Categories

Resources