Перейти к содержанию
Fire Monkey от А до Я
  • 0

Как открыть PDF в стандартном приложении просмотра PDF файлов?


Alexey

Вопрос

Рекомендуемые сообщения

  • 0
  • Администраторы

Открытие любого файла в подходящем приложении в операционной системе Андроид выполняются одинаковым способом.

  1. Путем посылки намерения (Интент) с указанием файла и типа данных.
  2. Далее система ищет по указанному типу файла, какие приложения зарегистрированы на обработку файлов этого типа,
  3. Если приложение, которое может обработать этот файл, одно, то запускает активити приложения и передает туда ваш файл/данные.
  4. Если приложений несколько - запускает диалоговое окно выбора приложения, которое будет выполнять обработку вашего файла.

Резюмируя это, смотрим на код:

uses
  System.IOUtils, FMX.Helpers.Android, Androidapi.JNI.Net, Androidapi.JNI.GraphicsContentViewText;

procedure TForm7.btnOpenPDFClick(Sender: TObject);
const
  SAMPLE_PDF_FILENAME = 'example.pdf';
var
  Uri: Jnet_Uri;
  OpenLinkIntent: JIntent;
  PDFFileName: string;
begin
  PDFFileName := TPath.Combine(TPath.GetDocumentsPath, SAMPLE_PDF_FILENAME);  { Внутренний доступ}
  Uri := StrToJURI(PDFFileName);
  // Формируем намерение об открытии файла в стандартном приложении
  OpenLinkIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, Uri);
  // Устанавливаем тип данных
  OpenLinkIntent.setType(StringToJString('application/pdf'));
  OpenLinkIntent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP);
  // Запускаем приложение и передаем ему наше намерение
  try
    SharedActivity.startActivity(OpenLinkIntent);
  except on E: Exception do
    ShowMessage('Не удалось открыть PDF. В системе нет доступных приложения для просмотра pdf');
  end;
end;

В этом код pdf файл берется из самого пакета приложения (я включил pdf файл в пакет приложения).

Если вам нужно вытащить файл в любом другом месте, просто укажите в PDFFileName полный путь к файлу в файловой системе вашего устройства.

 

Проект доступен тут: OpenPDF.zip

Ссылка на комментарий
  • 0

Добрый день!

 

При выполнении вышеуказанного проекта наблюдаю следующую картину - открывается PDF Reader, но не открывает сам запрашиваемый файл. С чем может быть связано такое поведение. Описанная ситуация наблюдается на телефоне и планшете.

Ссылка на комментарий
  • 0

Отвечу сам, следующие изменения позволили нормально просматривать PDF:

1. Открыть PDF удалось только из внешнего хранилища, иначе PDF Reader ругался на недопустимое имя файла.

2. Имя файла должно начинаться с file:

3. setType сбрасывал установленный Uri на файл данных, поэтому нужно использовать setDataAndType

Ссылка на комментарий
  • 0

Виталий просьба осветить вопрос поподробнее.

1. Что за внешнее хранилище ? Какой путь нужно ставить в деплоймент менеджере и какую функцию использовать для поиска файла ( GetDocumentsPath или GetSharedDocumentsPath) ?

2. Если у файла имя myDoc.pdf   Нужно ли указать : AFileName =  System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetSharedDocumentsPath(), L"file:MyDoc.pdf"); или как-то иначе ?

 

Ссылка на комментарий
  • 0
  • Модераторы
1 час назад, chaplin.u@gmail.com сказал:

Виталий просьба осветить вопрос поподробнее.

1. Что за внешнее хранилище ? Какой путь нужно ставить в деплоймент менеджере и какую функцию использовать для поиска файла ( GetDocumentsPath или GetSharedDocumentsPath) ?

2. Если у файла имя myDoc.pdf   Нужно ли указать : AFileName =  System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetSharedDocumentsPath(), L"file:MyDoc.pdf"); или как-то иначе ?

 

внешнее хранилище это карта памяти скорее всего.

папка GetDocumentsPath - доступна только для своего приложения, соответственно сторонние приложения доступа не имеют к ней

Ссылка на комментарий
  • 0

Оказалось что нужно класть в общедоступные папки а это чревато удалением нужного файла. А как в случае отсутствия файла дать ссылку на скачивание и запуск скаченного файла ?

Ссылка на комментарий
  • 0
  • Модераторы

выход можно сделать такой

1) оригинал всегда лежит в GetDocumentsPath. 

2) если его нужно открыть в сторонней программе, копируем в Download и передаем этот путь сторонней программе

 

Ссылка на комментарий
  • 1
function GetDefaultFilePath(const FileName: string): string;
begin
{$IFDEF Android}
  Result := TPath.Combine(TPath.GetSharedDocumentsPath, FileName);
{$ENDIF}
{$IFDEF IOS}
  Result := TPath.Combine(TPath.GetDocumentsPath, FileName);
{$ENDIF}
{$IFDEF MSWindows}
  Result := TPath.Combine(TPath.GetDocumentsPath, FileName);
{$ENDIF}
  ForceDirectories(ExtractFilePath(Result));
end;

procedure TForm.ShowPDF;
var
{$IFDEF Android}
  Intent: JIntent;
{$ENDIF}
  FilePath, tmpStr: string;
begin
  FilePath := GetDefaultFilePath(Filename);

{$IFDEF Android }
  try
    Intent := TJIntent.Create;
    Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
    Intent.setDataAndType(StrToJURI('file:' + FilePath),
      StringToJString('application/pdf'));
    Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NO_HISTORY);
    Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
    SharedActivity.startActivity(Intent);
  except
    on E: Exception do
      ShowToast(E.Message);
  end;

{$ENDIF}
{$IFDEF IOS}
  wbViewPDF.Visible := True;
  wbViewPDF.URL := 'file:/' + FilePath;
{$ENDIF}
end;

Приблизительно так...

Ссылка на комментарий
  • 1
  • Модераторы
18 минут назад, chaplin.u@gmail.com сказал:

спасибо .  

в Андроиде есть интенты а как на  IOS  запустить  например просмотр видео файла ?

на ios нету интентов, там все делается через url. открываете url и система сама откроет приложение если такое установлено

modURL.rar

Ссылка на комментарий
  • 0
  • Модераторы
9 минут назад, chaplin.u@gmail.com сказал:

тогда вопрос - почему для PDF нужно использовать TWebBrowser  а не  url ? Ведь PDF в IOS  родной формат ?

незнаю, видать так удобно было. даже если открыть pdf в браузере Сафари предлагает открыть его в iBooks

Ссылка на комментарий
  • 0
  • Модераторы
1 минуту назад, chaplin.u@gmail.com сказал:

когда открыл TWebBrowser  понял в чём разница. он же видимый. т.е у него есть окно в которое он выводит информацию а url открывает в отдельном окне.

эмм, на андроиде тоже откроется в отдельном окне...

Ссылка на комментарий
  • 0

фигня получается. так как код :  wbViewPDF.Visible := True;  делает видимым броузер

и он успешно открывает файл но закрыть его уже никак ! 

а методы открытия файла как ссылку не работает....

 

Ссылка на комментарий
  • 0

А у меня вообще что-то не получается...

Пишет - не получается открыть файл.

Я думал какие-то проблемы с папками - скинул PDF в проверенную папку - Downloads, написал кусок кода, который в этой же папке роется и формирует список файлов, чтобы понять, что программа в папку лезет..

 

 

procedure TForm7.btnOpenPDFClick(Sender: TObject);
const
  SAMPLE_PDF_FILENAME = '978.pdf';
var
  Uri: Jnet_Uri;
  OpenLinkIntent: JIntent;
  PDFFileName: string;
  sr:TSearchRec;
  bchars, Tws:TSysCharSet;
begin
PDFFileName :=TPath.Combine(TPath.GetSharedDownloadsPath, SAMPLE_PDF_FILENAME);  { Внутренний доступ}
  Label1.Text:=PDFFileName;


	if (FindFirst(TPath.GetSharedDownloadsPath+'/*.pdf', faAnyFile, sr) = 0) then
	begin
		Memo1.Lines.Add(sr.Name);

	  while (FindNext(sr) = 0) do
		 begin
			Memo1.Lines.Add(sr.Name);
		 end;
	end;
	FindClose(sr);


  Uri := StrToJURI(PDFFileName);
  // Формируем намерение об открытии файла в стандартном приложении
  OpenLinkIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, Uri);
  // Устанавливаем тип данных
  OpenLinkIntent.setType(StringToJString('application/pdf'));
  OpenLinkIntent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP);
  // Запускаем приложение и передаем ему наше намерение
  try
    SharedActivity.startActivity(OpenLinkIntent);
  except on E: Exception do
    ShowMessage('Не удалось открыть PDF. В системе нет доступных приложения для просмотра pdf');
  end;
end;

Что у меня не так?

Ссылка на комментарий
  • 0
Цитата

Если приложений несколько - запускает диалоговое окно выбора приложения, которое будет выполнять обработку вашего файла.

Вот! Как раз этого у меня и нет. У меня несколько приложений и когда я пытаюсь открыть файл из диспетчера - вопрос о программе задается.

А в мой программе - нет. Пишет - не удалось открыть файл.

Ссылка на комментарий
  • 0

Возникла проблема.

Как открыть файл на редактирование, так что бы WPS/MS офис мог потом его сохранить в тот же файл ?

Файл открывается из штатного проводника и сохраняется одним кликом.

Но вызывая его из моей программы, WPS как бы не знает откуда он его открыл, и не может сохранить в 1 клик.

Или как-то не так передаю файл программе или не хватает каких-то хедеров данных?


 



LFile := TJFile.JavaClass.init(StringToJString(AFilePath));

Intent.setDataAndType(TAndroidHelper.JFileToJURI(LFile), ExtToMime);

Intent.setFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION);

Intent.addFlags(TJIntent.JavaClass.FLAG_GRANT_WRITE_URI_PERMISSION);

 

Изменено пользователем Станислав Менинник
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...