Skip to content

Commit a96d97c

Browse files
committed
switch to using Fragments and ViewModel
- Host the WebView and all of its related code inside of a Fragment instead of an Activity. Fragments can give us more flexibility in the future on how we can display the WebView, how we could manage some bottom menu via a BottomNavigationView or similar, etc. - Use a ViewModel and LiveData architecture in order to move away from Loaders, which are now deprecated. Almost all state information for the viewer (like current page, zoom ratio) is now stored in the ViewModel, which survives configuration changes. - Rewrite the document property parsing in DocumentPropertiesLoader in Kotlin, taking advantage of Kotlin coroutines to do asynchronous parsing of the document properties. - Dynamically update the properties dialog after PDF loads. If viewing the PDF properties while the PDF loads, before, the dialog would show an error message. Now, the error message will be swapped out with the parsed info as soon the document properties have been parsed. This is done using an Observer on LiveData. - Use an alpha version of AndroidX Fragment so that we can use a simpler way to pass data between two Fragments: https://developer.android.com/training/basics/fragments/pass-data-between - Alpha version of Fragments also has ActivityResultLauncher, which simplifies the SAF launch https://developer.android.com/training/basics/intents/result "While the underlying startActivityForResult() and onActivityResult() APIs are available on the Activity class on all API levels, it is strongly recommended to use the Activity Result APIs introduced in AndroidX Activity 1.2.0-alpha02 and Fragment 1.3.0-alpha02." Closes GrapheneOS#69, GrapheneOS#70
1 parent 6f8a37c commit a96d97c

13 files changed

+416
-382
lines changed

app/build.gradle

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
apply plugin: 'com.android.application'
2+
apply plugin: 'kotlin-android'
23

34
android {
45
compileSdkVersion 29
@@ -36,6 +37,12 @@ dependencies {
3637
implementation fileTree(include: ['*.jar'], dir: 'libs')
3738
implementation 'androidx.appcompat:appcompat:1.1.0'
3839
implementation 'com.google.android.material:material:1.1.0'
40+
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
41+
implementation "androidx.core:core-ktx:1.3.1"
42+
implementation "androidx.fragment:fragment:1.3.0-alpha08"
43+
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
44+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
45+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
3946
}
4047

4148
def props = new Properties()
@@ -61,3 +68,6 @@ if (propFile.canRead()) {
6168
println 'signing.properties not found'
6269
android.buildTypes.release.signingConfig = null
6370
}
71+
repositories {
72+
mavenCentral()
73+
}

app/src/debug/res/values/strings.xml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="app_name">PDF Viewer Debug</string>
4+
</resources>

app/src/main/AndroidManifest.xml

+23-14
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
package="org.grapheneos.pdfviewer"
4-
android:targetSandboxVersion="2">
5-
<application android:icon="@mipmap/ic_launcher"
6-
android:roundIcon="@mipmap/ic_launcher_round"
7-
android:label="@string/app_name"
8-
android:theme="@style/AppTheme"
9-
android:allowBackup="true">
10-
<activity android:name=".PdfViewer"
11-
android:label="@string/app_name">
3+
package="org.grapheneos.pdfviewer"
4+
android:targetSandboxVersion="2">
5+
6+
<application
7+
android:allowBackup="true"
8+
android:icon="@mipmap/ic_launcher"
9+
android:label="@string/app_name"
10+
android:roundIcon="@mipmap/ic_launcher_round"
11+
android:theme="@style/AppTheme">
12+
<activity
13+
android:name=".PdfViewerActivity"
14+
android:label="@string/app_name">
1215
<intent-filter>
1316
<action android:name="android.intent.action.MAIN" />
17+
1418
<category android:name="android.intent.category.LAUNCHER" />
1519
</intent-filter>
1620
<intent-filter>
1721
<action android:name="android.intent.action.VIEW" />
22+
1823
<category android:name="android.intent.category.DEFAULT" />
1924
<category android:name="android.intent.category.BROWSABLE" />
25+
2026
<data android:mimeType="application/pdf" />
2127
</intent-filter>
2228
</activity>
2329

24-
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
25-
android:value="true" />
26-
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
27-
android:value="false" />
30+
<meta-data
31+
android:name="android.webkit.WebView.MetricsOptOut"
32+
android:value="true" />
33+
<meta-data
34+
android:name="android.webkit.WebView.EnableSafeBrowsing"
35+
android:value="false" />
2836
</application>
29-
</manifest>
37+
38+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.grapheneos.pdfviewer;
2+
3+
import android.os.Bundle;
4+
5+
import androidx.appcompat.app.AppCompatActivity;
6+
7+
public class PdfViewerActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_pdf_viewer);
13+
14+
if (savedInstanceState == null) {
15+
PdfViewerFragment fragment = PdfViewerFragment.newInstance();
16+
getSupportFragmentManager()
17+
.beginTransaction()
18+
.setPrimaryNavigationFragment(fragment)
19+
.add(R.id.pdf_fragment_container, fragment)
20+
.commit();
21+
}
22+
23+
}
24+
}

0 commit comments

Comments
 (0)