Download and open PDF file (XE7/Android) [Edit]

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
Benjamin
11/27/2014 9:55:41 AM
embarcadero.delphi.firemonkey 4901 articles. 4 followers. Follow

9 Replies
7865 Views

Similar Articles

[PageSpeed] 21

> {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
Adrian
11/27/2014 10:26:52 AM
{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
Benjamin
11/27/2014 11:37:31 AM
> {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
Adrian
11/27/2014 1:53:53 PM
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
Benjamin
11/27/2014 2:10:03 PM
> {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
Adrian
11/27/2014 3:34:23 PM
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
Benjamin
11/28/2014 10:11:24 AM
> {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
Adrian
11/28/2014 2:51:09 PM
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
Antonio
11/28/2014 3:56:53 PM
> {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
Benjamin
11/28/2014 3:59:38 PM
Reply:

Web resources about - Download and open PDF file (XE7/Android) [Edit] - embarcadero.delphi.firemonkey

Don't Download This Song - Wikipedia, the free encyclopedia
" Don't Download This Song " is the first single from "Weird Al" Yankovic 's 12th studio album Straight Outta Lynwood . The song was released ...

Facebook Adds To Download Your Information
Facebook increased the amount of information users can access when they download their account histories using the social network’s Download ...

Download the Facebook IQ digital magazine - Facebook for Business
The Facebook IQ digital magazine puts all the insights, best practices and key stats in one place. Download it on your mobile and read it anywhere. ...

Downloads
Download previous versions of the Facebook for iOS SDK.

‘Silent updates’ for Android download latest version of Facebook without Google Play
... users to receive app updates without going through the Google Play store. Some Android users are now receiving “silent updates,” which download ...

Lifehacker, tips and downloads for getting things done
Lifehacker curates tips, tricks, and technology for living better in the digital age.

Technology Product Reviews, News, Prices & Downloads - PCMag.com - PC Magazine
PC Magazine is your complete guide to PC computers, peripherals and upgrades. We test and review computer- and Internet-related products and ...

Indie Music News, MP3 Downloads, Music Videos, Reviews - Stereogum
MP3s downloads, music videos, concert reviews, tour dates and contests. Updated regularly.

RN Download ThisShow (@RNDownload) on Twitter
Log in Sign up You are on Twitter Mobile because you are using an old version of Internet Explorer. Learn more here RN Download ThisShow @ RNDownload ...

Final Fantasy IX is now available for download on iOS w/ special launch pricing
... the game itself, remember, this thing is a beast: “This application takes up around 4GB of memory. Over 8GB of free space is required to download ...

Resources last updated: 2/11/2016 4:02:56 AM