Skip to content

Commit

Permalink
Android PDF file viewer and openLink function working (#3268)
Browse files Browse the repository at this point in the history
  • Loading branch information
VitorVieiraZ committed May 22, 2024
1 parent baf5c4c commit dab98ac
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 2 deletions.
3 changes: 3 additions & 0 deletions app/android/res/xml/file_paths.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="input_camera" path="./" />
<external-path
name="app_files"
path="Android/data/uk.co.lutraconsulting/" />
</paths>
43 changes: 43 additions & 0 deletions app/android/src/uk/co/lutraconsulting/InputActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
import android.graphics.Insets;
import android.graphics.Color;

import android.content.Intent;
import android.net.Uri;
import android.content.ActivityNotFoundException;
import java.io.File;
import androidx.core.content.FileProvider;
import android.widget.Toast;

import androidx.core.view.WindowCompat;
import androidx.core.splashscreen.SplashScreen;

Expand Down Expand Up @@ -123,6 +130,42 @@ public void hideSplashScreen()
keepSplashScreenVisible = false;
}

public void openFile( String filePath ) {
Log.d( TAG, "Expected file path: " + filePath );

File file = new File( filePath );

if ( !file.exists() ) {
Log.d( TAG, "File does not exist: " + filePath );
runOnUiThread( () -> Toast.makeText( getApplicationContext(), "File not available", Toast.LENGTH_SHORT ).show() );
return;
} else {
Log.d( TAG, "File exists: " + filePath );
}

Intent showFileIntent = new Intent( Intent.ACTION_VIEW );

try {
Uri fileUri = FileProvider.getUriForFile( this, "uk.co.lutraconsulting.fileprovider", file );
Log.d( TAG, "File URI: " + fileUri.toString() );

showFileIntent.setData( fileUri );

// FLAG_GRANT_READ_URI_PERMISSION grants temporary read permission to the content URI.
// FLAG_ACTIVITY_NEW_TASK is used when starting an Activity from a non-Activity context.
showFileIntent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION );
} catch ( IllegalArgumentException e ) {
Log.d( TAG, "FileProvider URI issue", e );
return;
}

if ( showFileIntent.resolveActivity( getPackageManager() ) != null ) {
startActivity( showFileIntent );
} else {
runOnUiThread( () -> Toast.makeText( getApplicationContext(), "No application for opening this file", Toast.LENGTH_SHORT ).show() );
}
}

public void quitGracefully()
{
String man = android.os.Build.MANUFACTURER.toUpperCase();
Expand Down
9 changes: 9 additions & 0 deletions app/androidutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@ void AndroidUtils::hideSplashScreen()
#endif
}

void AndroidUtils::openFile( const QString &filePath )
{
#ifdef ANDROID
auto activity = QJniObject( QNativeInterface::QAndroidApplication::context() );
QJniObject jFilePath = QJniObject::fromString( filePath );
activity.callMethod<void>( "openFile", "(Ljava/lang/String;)V", jFilePath.object<jstring>() );
#endif
}

bool AndroidUtils::requestStoragePermission()
{
#ifdef ANDROID
Expand Down
1 change: 1 addition & 0 deletions app/androidutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class AndroidUtils: public QObject
*/
Q_INVOKABLE void callImagePicker( const QString &code = "" );
Q_INVOKABLE void callCamera( const QString &targetPath, const QString &code = "" );
Q_INVOKABLE void openFile( const QString &filePath );

#ifdef ANDROID
const static int MEDIA_CODE = 101;
Expand Down
36 changes: 35 additions & 1 deletion app/inpututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QRegularExpression>
#include <QDesktopServices>
#include <algorithm>
#include <limits>
#include <math.h>
Expand Down Expand Up @@ -2156,6 +2156,7 @@ QList<QgsPoint> InputUtils::parsePositionUpdates( const QString &data )
return parsedUpdates;
}

<<<<<<< HEAD
QString InputUtils::getManufacturer()
{
#ifdef Q_OS_ANDROID
Expand All @@ -2175,3 +2176,36 @@ QString InputUtils::getDeviceModel()
#endif
return QStringLiteral( "N/A" );
}

void InputUtils::openLink( const QString &homePath, const QString &link )
{
qDebug() << "LINK" << link;
qDebug() << "HOMEPATH" << homePath;

QString cleanedLink = link.trimmed();
static QRegularExpression re( "^\\?|\\?$" );
cleanedLink.remove( re );

qDebug() << "cleanedLink" << cleanedLink;

if ( cleanedLink.startsWith( "project://" ) )
{
QString relativePath = cleanedLink.mid( QString( "project://" ).length() );
QString absoluteLinkPath = homePath + QDir::separator() + relativePath;

qDebug() << "relativePath" << relativePath;
qDebug() << "absoluteLinkPath" << absoluteLinkPath;

#ifdef Q_OS_ANDROID
qDebug() << "openLink android";
mAndroidUtils->openFile( absoluteLinkPath );
#elif defined(Q_OS_IOS)
qDebug() << "openLink ios";
#endif
}
else
{
cleanedLink.chop( 1 ); //remove \ from cleanedLink
QDesktopServices::openUrl( QUrl( cleanedLink ) );
}
}
7 changes: 7 additions & 0 deletions app/inpututils.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ class InputUtils: public QObject
*/
Q_INVOKABLE static QString bytesToHumanSize( double bytes );

/**
* Opens the specified link in an appropriate application. For "project://" links, it converts them to
* absolute paths and opens with default file handlers. Other links are opened in the default web browser.
* @param link The link to open, either a "project://" link or a standard URL.
*/
Q_INVOKABLE void openLink( const QString &homePath, const QString &link );

Q_INVOKABLE bool acquireCameraPermission();

Q_INVOKABLE bool isBluetoothTurnedOn();
Expand Down
2 changes: 1 addition & 1 deletion app/qml/form/editors/MMFormTextMultilineEditor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ MMPrivateComponents.MMBaseInput {
radius: __style.radius12
}

onLinkActivated: ( link ) => Qt.openUrlExternally( link )
onLinkActivated: ( link ) => __inputUtils.openLink( root._fieldHomePath, link.toString() )
onTextChanged: root.editorValueChanged( textArea.text, textArea.text === "" )
}

Expand Down

0 comments on commit dab98ac

Please sign in to comment.