Hi, With the code below I try to download and open a pdf file on Android. {code} sPath := TPath.Combine(TPath.GetDocumentsPath, 'XXX.pdf'); DeleteFile(sPath); MemoryStream := TMemoryStream.Create; IdHTTP1.Get('http://XXX.com/files/XXX.pdf', MemoryStream); MemoryStream.SaveToFile(sPath); if FileExists(sPath) then begin Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.setDataAndType(StrToJURI(sPath), StringToJString('application/pdf')); SharedActivity.StartActivity(Intent); end; {code} FileExists return true so I assume that the file is correctly downloaded. But after the last command (StartActivity), I have the "File or folder not found" notification on android device. If someone could help me.... Thanks in advance ;) Ben Edited by: Benjamin Cabot on Nov 27, 2014 1:55 AM
![]() |
0 |
![]() |
> {quote:title=Benjamin Cabot wrote:}{quote} > Hi, > > With the code below I try to download and open a pdf file on Android. > > {code} > sPath := TPath.Combine(TPath.GetDocumentsPath, 'XXX.pdf'); > {code} > You might try to use: {code} sPath := TPath.Combine(TPath.GetSHAREDDocumentsPath, 'XXX.pdf'); {code} Android needs the file to be in external storage in order to share it. You can't share a file in GetDocumentsPath, it must be GetSHAREDDocumentsPath. And in order to access the external storage, you need to add permissions for external storage in the Application Properties. Edited by: Adrian Gallero on Nov 27, 2014 2:25 AM
![]() |
0 |
![]() |
{quote:title=Adrian Gallero wrote:} Android needs the file to be in external storage in order to share it. You can't share a file in GetDocumentsPath, it must be GetSHAREDDocumentsPath. And in order to access the external storage, you need to add permissions for external storage in the Application Properties. {quote} Thank you for your help, but it is the same with GetDocumentsPath. And as you can see above, permissions were done. {code}<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />{code}
![]() |
0 |
![]() |
> {quote:title=Benjamin Cabot wrote:}{quote} > {quote:title=Adrian Gallero wrote:} > > Android needs the file to be in external storage in order to share it. You can't share a file in GetDocumentsPath, it must be GetSHAREDDocumentsPath. > And in order to access the external storage, you need to add permissions for external storage in the Application Properties. > > {quote} > > Thank you for your help, but it is the same with GetDocumentsPath. > Is GetDocumentsPath or Get*Shared*Documents path? GetDocumentPath is a private folder for your app, and so nobody else can access it. SharedDocumentsPath is a folder that other can see. If SharedDocumentsPath isn't working, can you try any folder in the device that you know any app can access? From your description, it seems that you have the permissions to write in the folder (that's why no errors on your side), but the pdf viewer doesn't have the permissions to see the file (that's why the error appears when you try to share the file)
![]() |
0 |
![]() |
Of course it was GetSHAREDDocumentsPath and it did not work. I'm not very familiar with Android. Do you have a suggestion for a free access directory that I can use?
![]() |
0 |
![]() |
> {quote:title=Benjamin Cabot wrote:}{quote} > Of course it was GetSHAREDDocumentsPath and it did not work. > > I'm not very familiar with Android. Do you have a suggestion for a free access directory that I can use? It really depends in the device you are using. But anyway, looking at your code, I am not sure if that is the correct code. Can you try with something like this? (I changed the indy component to a resourcestream just to make is simpler for me to test, but you can keep the indy component) unit Unit4; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, IOUtils, Androidapi.JNI.Net, Androidapi.JNI.Os, Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, AndroidAPI.JNI.JavaTypes; type TForm4 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private Intent: JIntent; { Private declarations } public { Public declarations } end; var Form4: TForm4; implementation {$R *.fmx} procedure TForm4.Button1Click(Sender: TObject); var sPath: string; MemoryStream: TResourceStream; fileuri: JParcelable; begin sPath := TPath.Combine(TPath.GetSharedDocumentsPath, 'XXX.pdf'); DeleteFile(sPath); MemoryStream := TResourceStream.Create(hinstance, 'xxx', RT_RCDATA); MemoryStream.SaveToFile(sPath); if FileExists(sPath) then begin fileuri := JParcelable(TJNet_Uri.JavaClass.fromFile(TJFile.JavaClass.init(StringToJString(sPath)))); Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); intent.setType(StringToJString('application/pdf')); Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, fileuri); SharedActivity.StartActivity(Intent); end; end; end. Some notes in the code: 1)In my own, I use ACTION_SEND, not ACTION_VIEW It didn't really work here with ACTION_VIEW (quickoffice stops working) but it might be something on my tablet. If ACTION_VIEW doesn't work for you either, you might try ACTION_SEND 2)The Intent is not a local variable but a global one. I don't remember the specifics, but I think that if you made it local, then the intent would be freed by arc when leaving the procedure, so it would crash. But I don't rememeber if this was for iOS or for android. In any case, I made it global just in case.
![]() |
0 |
![]() |
Thank you so much for the time you spent for me! So I tried the code below... {code} var sPath: string; MemoryStream: TMemoryStream; fileuri: JParcelable; begin sPath := TPath.Combine(TPath.GetSharedDocumentsPath, 'xxx.pdf'); DeleteFile(sPath); MemoryStream := TMemoryStream.Create; IdHTTP1.Get('http://xxx.com/xxx.pdf', MemoryStream); MemoryStream.SaveToFile(sPath); if FileExists(sPath) then begin fileuri := JParcelable(TJNet_Uri.JavaClass.fromFile(TJFile.JavaClass.init(StringToJString(sPath)))); Intent := TJIntent.Create; // Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.setAction(TJIntent.JavaClass.ACTION_SEND); intent.setType(StringToJString('application/pdf')); Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, fileuri); SharedActivity.StartActivity(Intent); end; end; {code} ....and I have the same issue than you (quickoffice crash at opening) with VIEW. With SEND it opens the export dialog and I can send it by email, bluetooth,... successfully. So now there is no issue for downloading the file and access it. The issue is regarding the quickoffice opening...
![]() |
0 |
![]() |
> {quote:title=Benjamin Cabot wrote:}{quote} > ...and I have the same issue than you (quickoffice crash at opening) with VIEW. > With SEND it opens the export dialog and I can send it by email, bluetooth,... successfully. > > So now there is no issue for downloading the file and access it. > The issue is regarding the quickoffice opening... Yes, that seems weird. From what I found, it looks like the call to SetType clears the data, and a call to setdata clears the type. So we need to set them both with SetDataAndType. So I tried going back to your original code, and changing the url to start with file:// and now it seems to work: Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); intent.setDataAndType(StrToJURI('file://' + spath) ,StringToJString('application/pdf')); SharedActivity.StartActivity(Intent); (Of course, I think there are some URI routines somewhere that will add the file://, but I didn't want to search for them) So I think with the following 2 changes over the original code: 1)Change Documents by SharedDocuments 2)Add 'file://' to the uri It should work. It works here, at least.
![]() |
0 |
![]() |
El 28/11/14 a las 11:11, Benjamin Cabot escribió: > {code} > var > sPath: string; > MemoryStream: TMemoryStream; > fileuri: JParcelable; > begin > > sPath := TPath.Combine(TPath.GetSharedDocumentsPath, 'xxx.pdf'); > > DeleteFile(sPath); > > MemoryStream := TMemoryStream.Create; > > IdHTTP1.Get('http://xxx.com/xxx.pdf', MemoryStream); > > MemoryStream.SaveToFile(sPath); > > if FileExists(sPath) then > begin > > fileuri := JParcelable(TJNet_Uri.JavaClass.fromFile(TJFile.JavaClass.init(StringToJString(sPath)))); > Intent := TJIntent.Create; > // Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); > Intent.setAction(TJIntent.JavaClass.ACTION_SEND); > intent.setType(StringToJString('application/pdf')); > Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, fileuri); > SharedActivity.StartActivity(Intent); > > end; > end; > {code} > Edited by: Antonio Estevez on Nov 28, 2014 7:56 AM
![]() |
0 |
![]() |
> {quote:title=Adrian Gallero wrote:}{quote} > > {quote:title=Benjamin Cabot wrote:}{quote} > > ...and I have the same issue than you (quickoffice crash at opening) with VIEW. > > With SEND it opens the export dialog and I can send it by email, bluetooth,... successfully. > > > > So now there is no issue for downloading the file and access it. > > The issue is regarding the quickoffice opening... > > Yes, that seems weird. From what I found, it looks like the call to SetType clears the data, and a call to setdata clears the type. So we need to set them both with SetDataAndType. > > So I tried going back to your original code, and changing the url to start with file:// and now it seems to work: > > Intent := TJIntent.Create; > Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); > intent.setDataAndType(StrToJURI('file://' + spath) ,StringToJString('application/pdf')); > SharedActivity.StartActivity(Intent); > > > (Of course, I think there are some URI routines somewhere that will add the file://, but I didn't want to search for them) > > So I think with the following 2 changes over the original code: > 1)Change Documents by SharedDocuments > 2)Add 'file://' to the uri > > It should work. It works here, at least. GREAT!!!! It works perfectly as it! Thank you very much for your help Adrian.
![]() |
0 |
![]() |