Перейти к содержанию
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
  • Модераторы
Опубликовано

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

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
Опубликовано

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

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

Я думал какие-то проблемы с папками - скинул 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 эмодзи.

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

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

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

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