如果說你要開啟的檔案是存在於網際網路上,比如

http://etds.lib.ntnu.edu.tw/gs/ntnu/doc/convert.pdf

或是你的檔案已經打包到 ipa 檔案中,那麼這篇文章提到的方法就不適用,因為不論程式怎麼寫,應該都可以順利開啟...

本篇文章最主要要說明(解決)的,是針對要開啟的檔案存放於 local,並且檔案是經由動態產生或是即時下載的

首先要先思考的是,要在 iOS 上開啟各種檔案有什麼方式呢?回想一下在 android 上的作法,基本上是丟給作業系統解決,比如 pdf  檔案必須要有安裝 pdf reader 的 app 才有辦法開啟,那 iOS 的話呢?

查了一下 google 大師,一下子查不到 iOS 上的作法(pdf reader ?),似乎 iOS 上的安全性比較嚴格,由於 app 都在沙箱內運作,包含 app 運作過程產生(儲存)的檔案,其他 app 接觸不到,所以如果 app 下載了一個 pdf 檔案,想要用 pdf reader app 開啟它,無疑是緣木求魚,應該是做不到的!

於似乎筆者的想法是,如果改用 TWebBrowser 開啟各式檔案呢?雖然 TWebBrowser 能開啟的檔案種類有限,但是至少常見的 jpg、txt、pdf 等都不是問題,讓我們做個實驗一下吧...

先用兩個 TRectangle 載入不同的圖片,然後分別用兩個 button 將圖片以隨機檔案名稱儲存後,要求 TWebBrowser 載入

畫面如下

按下左邊 button 後,可以看到 apple 的圖片粉正常的顯示在 TWebBrower 上,如下圖

接下來按下右邊的 button,原本預期 TWebBrowser 應該要載入 android 的圖片,但是卻沒有反應?TWebBrowser 仍是保留 apple 的圖片....難道 EMBT 比較喜歡 apple ?

我想應該不是,如果你一開始點的是右邊的 button,那就改成一直都只顯示 android 的圖片嚕...

上述程式原始碼如下

unit uMain;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
  FMX.StdCtrls, FMX.WebBrowser;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    btnSaveLoadApple: TButton;
    btnSaveLoadAndroid: TButton;
    rtAndroid: TRectangle;
    rtApple: TRectangle;
    WebBrowser1: TWebBrowser;
    procedure FormResize(Sender: TObject);
    procedure btnSaveLoadAppleClick(Sender: TObject);
    procedure btnSaveLoadAndroidClick(Sender: TObject);
  private
    { Private declarations }
    function GetSaveFileName : string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  System.IOUtils;

procedure TForm1.btnSaveLoadAndroidClick(Sender: TObject);
var
  lTempFileName : string;
begin
  lTempFileName := GetSaveFileName;

  rtAndroid.Fill.Bitmap.Bitmap.SaveToFile(lTempFileName);

  WebBrowser1.Url := 'file:/' + lTempFileName;
end;

procedure TForm1.btnSaveLoadAppleClick(Sender: TObject);
var
  lTempFileName : string;
begin
  lTempFileName := GetSaveFileName;

  rtApple.Fill.Bitmap.Bitmap.SaveToFile(lTempFileName);

  WebBrowser1.Url := 'file:/' + lTempFileName;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  rtApple.Width := ClientWidth div 2;
end;

function TForm1.GetSaveFileName: string;
begin
  Result := TPath.GetDocumentsPath + PathDelim + IntToStr(Random(1000)) + '.jpg';
end;

end.

 

其實不管是 txt、pdf 或是其他 TWebBrowser 可以顯示的檔案格式,都有類似的狀況,查詢了一下 google 大師,在官方討論區曾有人發問類似的問題

https://forums.embarcadero.com/thread.jspa?threadID=103744

不過卻沒有解答...筆者無法確定這是 delphi 的問題,還是因為使用 native iOS control 才產生的狀況,既然這個方法行不通,那麼只好尋求其他解了...

在嘗試了其他許多方法後,筆者最後是選擇使用 D.P.F Delphi iOS Native Components,要用 Native Component,也代表著這個解決方案無法跨平台使用,這是筆者最不樂見的解決方式,畢竟當初要用 delphi,不就是衝著寫一次可以通用 android/ios 兩大平台而來的嗎...但這是筆者目前唯一測試出能滿足所需的解決方式了...

D.P.F Delphi iOS Native Components 是一套 open source 的元件集,下載完成後,按照 Install.txt  檔案內的說明就可以把元件安裝到 XE5/XE6 中了,步驟跟平常其他的元件比起來會比較繁複,畢竟是要跟 iOS 的環境作搭配,只要一步一步照著說明文件作,應該是可以順利完成的。

如果安裝成功,在 delphi 元件盤中應該可以看到多出一個頁籤是關於 D.P.F Components iOS 的

接下來筆者是用其中 TDPFQLPreviewController 這個元件來代替 TWebBrowser,這時候不管按下左邊還是右邊的 button 都可以正確顯示嚕...

附上更新後的 source code

unit uMain;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
  FMX.StdCtrls, FMX.WebBrowser, DPF.iOS.BaseControl, DPF.iOS.QLPreviewController;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    btnSaveLoadApple: TButton;
    btnSaveLoadAndroid: TButton;
    rtAndroid: TRectangle;
    rtApple: TRectangle;
    WebBrowser1: TWebBrowser;
    DPFQLPreviewController1: TDPFQLPreviewController;
    procedure FormResize(Sender: TObject);
    procedure btnSaveLoadAppleClick(Sender: TObject);
    procedure btnSaveLoadAndroidClick(Sender: TObject);
  private
    { Private declarations }
    function GetSaveFileName : string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  System.IOUtils;

procedure TForm1.btnSaveLoadAndroidClick(Sender: TObject);
var
  lTempFileName : string;
begin
  lTempFileName := GetSaveFileName;

  rtAndroid.Fill.Bitmap.Bitmap.SaveToFile(lTempFileName);

  //WebBrowser1.Url := 'file:/' + lTempFileName;
  DPFQLPreviewController1.ShowDoc(lTempFileName, false);
end;

procedure TForm1.btnSaveLoadAppleClick(Sender: TObject);
var
  lTempFileName : string;
begin
  lTempFileName := GetSaveFileName;

  rtApple.Fill.Bitmap.Bitmap.SaveToFile(lTempFileName);

  //WebBrowser1.Url := 'file:/' + lTempFileName;
  DPFQLPreviewController1.ShowDoc(lTempFileName, false);
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  rtApple.Width := ClientWidth div 2;
end;

function TForm1.GetSaveFileName: string;
begin
  Result := TPath.GetDocumentsPath + PathDelim + IntToStr(Random(1000)) + '.jpg';
end;

end.

比賽結束!

 

to be continued....

    縹緲 發表在 痞客邦 留言(0) 人氣()