libpdfviewer: Genesis

This commit is contained in:
Matéo Duparc 2022-02-18 15:03:53 +01:00
parent fdf2cf8c27
commit 4e4b7c5da4
Signed by: hardcoresushi
GPG Key ID: 007F84120107191E
27 changed files with 110 additions and 375 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "pdfjs-dist"]
path = third_party/pdfjs-dist
path = app/pdfjs-dist
url = https://github.com/mozilla/pdfjs-dist.git

View File

@ -9,7 +9,7 @@ if (useKeystoreProperties) {
}
plugins {
id("com.android.application")
id("com.android.library")
id("kotlin-android")
}
@ -29,21 +29,13 @@ android {
buildToolsVersion = "32.0.0"
defaultConfig {
applicationId = "org.grapheneos.pdfviewer"
minSdk = 26
minSdk = 21
targetSdk = 31
versionCode = 10
versionName = versionCode.toString()
resourceConfigurations.add("en")
}
buildTypes {
getByName("debug") {
applicationIdSuffix = ".debug"
}
getByName("release") {
isShrinkResources = true
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
if (useKeystoreProperties) {

View File

@ -2,25 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.grapheneos.pdfviewer"
android:targetSandboxVersion="2">
<application android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:allowBackup="true">
<activity android:name=".PdfViewer"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/pdf" />
</intent-filter>
</activity>
<application>
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"

View File

@ -1 +1 @@
../../../../third_party/pdfjs-dist/build/pdf.min.js
../../../pdfjs-dist/build/pdf.min.js

View File

@ -1 +1 @@
../../../../third_party/pdfjs-dist/build/pdf.worker.min.js
../../../pdfjs-dist/build/pdf.worker.min.js

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -2,8 +2,6 @@ package org.grapheneos.pdfviewer;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
@ -13,7 +11,6 @@ import android.view.View;
class GestureHelper {
public interface GestureListener {
boolean onTapUp();
// Can be replaced with ratio when supported
void onZoomIn(float value);
void onZoomOut(float value);
@ -22,15 +19,6 @@ class GestureHelper {
@SuppressLint("ClickableViewAccessibility")
static void attach(Context context, View gestureView, GestureListener listener) {
final GestureDetector detector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return listener.onTapUp();
}
});
final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context,
new ScaleGestureDetector.SimpleOnScaleGestureListener() {
final float SPAN_RATIO = 600;
@ -67,7 +55,6 @@ class GestureHelper {
});
gestureView.setOnTouchListener((view, motionEvent) -> {
detector.onTouchEvent(motionEvent);
scaleDetector.onTouchEvent(motionEvent);
return false;
});

View File

@ -1,18 +1,16 @@
package org.grapheneos.pdfviewer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface;
import android.webkit.WebResourceRequest;
@ -24,13 +22,11 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import com.google.android.material.snackbar.Snackbar;
import org.grapheneos.pdfviewer.databinding.WebviewBinding;
import org.grapheneos.pdfviewer.fragment.DocumentPropertiesFragment;
import org.grapheneos.pdfviewer.fragment.JumpToPageFragment;
import org.grapheneos.pdfviewer.loader.DocumentPropertiesLoader;
@ -40,13 +36,9 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
public class PdfViewer extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<CharSequence>> {
public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<List<CharSequence>> {
public static final String TAG = "PdfViewer";
private static final String STATE_URI = "uri";
private static final String STATE_PAGE = "page";
private static final String STATE_ZOOM_RATIO = "zoomRatio";
private static final String STATE_DOCUMENT_ORIENTATION_DEGREES = "documentOrientationDegrees";
private static final String KEY_PROPERTIES = "properties";
private static final String CONTENT_SECURITY_POLICY =
@ -92,12 +84,10 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
private static final float MAX_ZOOM_RATIO = 1.5f;
private static final int ALPHA_LOW = 130;
private static final int ALPHA_HIGH = 255;
private static final int ACTION_OPEN_DOCUMENT_REQUEST_CODE = 1;
private static final int STATE_LOADED = 1;
private static final int STATE_END = 2;
private static final int PADDING = 10;
private Uri mUri;
public int mPage;
public int mNumPages;
private float mZoomRatio = 1f;
@ -107,70 +97,27 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
private List<CharSequence> mDocumentProperties;
private InputStream mInputStream;
private WebviewBinding binding;
private TextView mTextView;
private Toast mToast;
private Snackbar snackbar;
private class Channel {
@JavascriptInterface
public int getWindowInsetTop() {
return windowInsetTop;
}
public AppCompatActivity activity;
String fileName;
Long fileSize;
@JavascriptInterface
public int getPage() {
return mPage;
}
@JavascriptInterface
public float getZoomRatio() {
return mZoomRatio;
}
@JavascriptInterface
public int getDocumentOrientationDegrees() {
return mDocumentOrientationDegrees;
}
@JavascriptInterface
public void setNumPages(int numPages) {
mNumPages = numPages;
runOnUiThread(PdfViewer.this::invalidateOptionsMenu);
}
@JavascriptInterface
public void setDocumentProperties(final String properties) {
if (mDocumentProperties != null) {
throw new SecurityException("mDocumentProperties not null");
}
final Bundle args = new Bundle();
args.putString(KEY_PROPERTIES, properties);
runOnUiThread(() -> LoaderManager.getInstance(PdfViewer.this).restartLoader(DocumentPropertiesLoader.ID, args, PdfViewer.this));
}
}
@Override
@SuppressLint({"SetJavaScriptEnabled", "ClickableViewAccessibility"})
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = WebviewBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.webview.setBackgroundColor(Color.TRANSPARENT);
void init(Context context) {
setBackgroundColor(Color.TRANSPARENT);
if (BuildConfig.DEBUG) {
WebView.setWebContentsDebuggingEnabled(true);
}
binding.webview.setOnApplyWindowInsetsListener((view, insets) -> {
setOnApplyWindowInsetsListener((view, insets) -> {
windowInsetTop = insets.getSystemWindowInsetTop();
binding.webview.evaluateJavascript("updateInset()", null);
evaluateJavascript("updateInset()", null);
return insets;
});
final WebSettings settings = binding.webview.getSettings();
final WebSettings settings = getSettings();
settings.setAllowContentAccess(false);
settings.setAllowFileAccess(false);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
@ -178,12 +125,12 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
CookieManager.getInstance().setAcceptCookie(false);
binding.webview.addJavascriptInterface(new Channel(), "channel");
addJavascriptInterface(new Channel(), "channel");
binding.webview.setWebViewClient(new WebViewClient() {
setWebViewClient(new WebViewClient() {
private WebResourceResponse fromAsset(final String mime, final String path) {
try {
InputStream inputStream = getAssets().open(path.substring(1));
InputStream inputStream = context.getAssets().open(path.substring(1));
return new WebResourceResponse(mime, null, inputStream);
} catch (IOException e) {
return null;
@ -237,30 +184,12 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
@Override
public void onPageFinished(WebView view, String url) {
mDocumentState = STATE_LOADED;
invalidateOptionsMenu();
activity.invalidateOptionsMenu();
}
});
GestureHelper.attach(PdfViewer.this, binding.webview,
GestureHelper.attach(context, this,
new GestureHelper.GestureListener() {
@Override
public boolean onTapUp() {
if (mUri != null) {
binding.webview.evaluateJavascript("isTextSelected()", selection -> {
if (!Boolean.parseBoolean(selection)) {
if ((getWindow().getDecorView().getSystemUiVisibility() &
View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
hideSystemUi();
} else {
showSystemUi();
}
}
});
return true;
}
return false;
}
@Override
public void onZoomIn(float value) {
zoomIn(value, false);
@ -277,56 +206,82 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
}
});
mTextView = new TextView(this);
mTextView = new TextView(context);
mTextView.setBackgroundColor(Color.DKGRAY);
mTextView.setTextColor(ColorStateList.valueOf(Color.WHITE));
mTextView.setTextSize(18);
mTextView.setPadding(PADDING, 0, PADDING, 0);
// If loaders are not being initialized in onCreate(), the result will not be delivered
// after orientation change (See FragmentHostCallback), thus initialize the
// loader manager impl so that the result will be delivered.
LoaderManager.getInstance(this);
snackbar = Snackbar.make(binding.webview, "", Snackbar.LENGTH_LONG);
final Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
if (!"application/pdf".equals(intent.getType())) {
snackbar.setText(R.string.invalid_mime_type).show();
return;
}
mUri = intent.getData();
mPage = 1;
}
if (savedInstanceState != null) {
mUri = savedInstanceState.getParcelable(STATE_URI);
mPage = savedInstanceState.getInt(STATE_PAGE);
mZoomRatio = savedInstanceState.getFloat(STATE_ZOOM_RATIO);
mDocumentOrientationDegrees = savedInstanceState.getInt(STATE_DOCUMENT_ORIENTATION_DEGREES);
public PdfViewer(@NonNull Context context) {
super(context);
init(context);
}
if (mUri != null) {
if ("file".equals(mUri.getScheme())) {
snackbar.setText(R.string.legacy_file_uri).show();
return;
public PdfViewer(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
loadPdf();
public PdfViewer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void onCreateOptionMenu(Menu menu) {
MenuInflater inflater = activity.getMenuInflater();
inflater.inflate(R.menu.pdf_viewer, menu);
}
private class Channel {
@JavascriptInterface
public int getWindowInsetTop() {
return windowInsetTop;
}
@JavascriptInterface
public int getPage() {
return mPage;
}
@JavascriptInterface
public float getZoomRatio() {
return mZoomRatio;
}
@JavascriptInterface
public int getDocumentOrientationDegrees() {
return mDocumentOrientationDegrees;
}
@JavascriptInterface
public void setNumPages(int numPages) {
mNumPages = numPages;
activity.runOnUiThread(activity::invalidateOptionsMenu);
}
@JavascriptInterface
public void setDocumentProperties(final String properties) {
if (mDocumentProperties != null) {
throw new SecurityException("mDocumentProperties not null");
}
final Bundle args = new Bundle();
args.putString(KEY_PROPERTIES, properties);
activity.runOnUiThread(() -> LoaderManager.getInstance(PdfViewer.this.activity).restartLoader(DocumentPropertiesLoader.ID, args, PdfViewer.this));
}
}
@NonNull
@Override
public Loader<List<CharSequence>> onCreateLoader(int id, Bundle args) {
return new DocumentPropertiesLoader(this, args.getString(KEY_PROPERTIES), mNumPages, mUri);
return new DocumentPropertiesLoader(activity, args.getString(KEY_PROPERTIES), mNumPages, fileName, fileSize);
}
@Override
public void onLoadFinished(@NonNull Loader<List<CharSequence>> loader, List<CharSequence> data) {
mDocumentProperties = data;
LoaderManager.getInstance(this).destroyLoader(DocumentPropertiesLoader.ID);
LoaderManager.getInstance(activity).destroyLoader(DocumentPropertiesLoader.ID);
}
@Override
@ -334,23 +289,18 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
mDocumentProperties = null;
}
private void loadPdf() {
try {
if (mInputStream != null) {
mInputStream.close();
}
mInputStream = getContentResolver().openInputStream(mUri);
} catch (IOException e) {
snackbar.setText(R.string.io_error).show();
return;
}
showSystemUi();
binding.webview.loadUrl("https://localhost/viewer.html");
public void loadPdf(InputStream inputStream, String fileName, Long fileSize) {
mPage = 1;
mDocumentProperties = null;
mInputStream = inputStream;
this.fileName = fileName;
this.fileSize = fileSize;
loadUrl("https://localhost/viewer.html");
activity.invalidateOptionsMenu();
}
private void renderPage(final int zoom) {
binding.webview.evaluateJavascript("onRenderPage(" + zoom + ")", null);
evaluateJavascript("onRenderPage(" + zoom + ")", null);
}
private void documentOrientationChanged(final int orientationDegreesOffset) {
@ -361,18 +311,11 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
renderPage(0);
}
private void openDocument() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/pdf");
startActivityForResult(intent, ACTION_OPEN_DOCUMENT_REQUEST_CODE);
}
private void zoomIn(float value, boolean end) {
if (mZoomRatio < MAX_ZOOM_RATIO) {
mZoomRatio = Math.min(mZoomRatio + value, MAX_ZOOM_RATIO);
renderPage(end ? 1 : 2);
invalidateOptionsMenu();
activity.invalidateOptionsMenu();
}
}
@ -380,7 +323,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
if (mZoomRatio > MIN_ZOOM_RATIO) {
mZoomRatio = Math.max(mZoomRatio - value, MIN_ZOOM_RATIO);
renderPage(end ? 1 : 2);
invalidateOptionsMenu();
activity.invalidateOptionsMenu();
}
}
@ -403,48 +346,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
mPage = selected_page;
renderPage(0);
showPageNumber();
invalidateOptionsMenu();
}
}
private void showSystemUi() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
private void hideSystemUi() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE);
}
@Override
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putParcelable(STATE_URI, mUri);
savedInstanceState.putInt(STATE_PAGE, mPage);
savedInstanceState.putFloat(STATE_ZOOM_RATIO, mZoomRatio);
savedInstanceState.putInt(STATE_DOCUMENT_ORIENTATION_DEGREES, mDocumentOrientationDegrees);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
if (requestCode == ACTION_OPEN_DOCUMENT_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if (resultData != null) {
mUri = resultData.getData();
mPage = 1;
mDocumentProperties = null;
loadPdf();
invalidateOptionsMenu();
}
activity.invalidateOptionsMenu();
}
}
@ -453,22 +355,13 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
mToast.cancel();
}
mTextView.setText(String.format("%s/%s", mPage, mNumPages));
mToast = new Toast(getApplicationContext());
mToast = new Toast(activity);
mToast.setGravity(Gravity.BOTTOM | Gravity.END, PADDING, PADDING);
mToast.setDuration(Toast.LENGTH_SHORT);
mToast.setView(mTextView);
mToast.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.pdf_viewer, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
final int[] ids = { R.id.action_zoom_in, R.id.action_zoom_out, R.id.action_jump_to_page,
R.id.action_next, R.id.action_previous, R.id.action_first, R.id.action_last,
@ -499,7 +392,6 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int itemId = item.getItemId();
if (itemId == R.id.action_previous) {
@ -514,9 +406,6 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
} else if (itemId == R.id.action_last) {
onJumpToPageInDocument(mNumPages);
return true;
} else if (itemId == R.id.action_open) {
openDocument();
return true;
} else if (itemId == R.id.action_zoom_out) {
zoomOut(0.25f, true);
return true;
@ -532,14 +421,13 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader
} else if (itemId == R.id.action_view_document_properties) {
DocumentPropertiesFragment
.newInstance(mDocumentProperties)
.show(getSupportFragmentManager(), DocumentPropertiesFragment.TAG);
.show(activity.getSupportFragmentManager(), DocumentPropertiesFragment.TAG);
return true;
} else if (itemId == R.id.action_jump_to_page) {
new JumpToPageFragment()
.show(getSupportFragmentManager(), JumpToPageFragment.TAG);
JumpToPageFragment.newInstance(this)
.show(activity.getSupportFragmentManager(), JumpToPageFragment.TAG);
return true;
}
return super.onOptionsItemSelected(item);
return false;
}
}

View File

@ -20,15 +20,12 @@ public class JumpToPageFragment extends DialogFragment {
private final static String STATE_PICKER_MAX = "picker_max";
private NumberPicker mPicker;
PdfViewer pdfViewer;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mPicker.setMinValue(savedInstanceState.getInt(STATE_PICKER_MIN));
mPicker.setMaxValue(savedInstanceState.getInt(STATE_PICKER_MAX));
mPicker.setValue(savedInstanceState.getInt(STATE_PICKER_CUR));
}
public static JumpToPageFragment newInstance(PdfViewer pdfViewer) {
JumpToPageFragment f = new JumpToPageFragment();
f.pdfViewer = pdfViewer;
return f;
}
@NonNull
@ -36,8 +33,8 @@ public class JumpToPageFragment extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
mPicker = new NumberPicker(getActivity());
mPicker.setMinValue(1);
mPicker.setMaxValue(((PdfViewer)requireActivity()).mNumPages);
mPicker.setValue(((PdfViewer)requireActivity()).mPage);
mPicker.setMaxValue(pdfViewer.mNumPages);
mPicker.setValue(pdfViewer.mPage);
final FrameLayout layout = new FrameLayout(getActivity());
layout.addView(mPicker, new FrameLayout.LayoutParams(
@ -49,7 +46,7 @@ public class JumpToPageFragment extends DialogFragment {
.setView(layout)
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
mPicker.clearFocus();
((PdfViewer)requireActivity()).onJumpToPageInDocument(mPicker.getValue());
pdfViewer.onJumpToPageInDocument(mPicker.getValue());
})
.setNegativeButton(android.R.string.cancel, null)
.create();

View File

@ -1,10 +1,7 @@
package org.grapheneos.pdfviewer.loader;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Typeface;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;
@ -12,6 +9,8 @@ import android.util.Log;
import androidx.loader.content.AsyncTaskLoader;
import org.grapheneos.pdfviewer.R;
import org.grapheneos.pdfviewer.Utils;
import org.json.JSONException;
import org.json.JSONObject;
@ -19,9 +18,6 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import org.grapheneos.pdfviewer.R;
import org.grapheneos.pdfviewer.Utils;
public class DocumentPropertiesLoader extends AsyncTaskLoader<List<CharSequence>> {
public static final String TAG = "DocumentPropertiesLoader";
@ -29,16 +25,17 @@ public class DocumentPropertiesLoader extends AsyncTaskLoader<List<CharSequence>
private final String mProperties;
private final int mNumPages;
private final Uri mUri;
private Cursor mCursor;
String fileName;
Long fileSize;
public DocumentPropertiesLoader(Context context, String properties, int numPages, Uri uri) {
public DocumentPropertiesLoader(Context context, String properties, int numPages, String fileName, Long fileSize) {
super(context);
mProperties = properties;
mNumPages = numPages;
mUri = uri;
this.fileName = fileName;
this.fileSize = fileSize;
}
@Override
@ -48,23 +45,8 @@ public class DocumentPropertiesLoader extends AsyncTaskLoader<List<CharSequence>
final String[] names = context.getResources().getStringArray(R.array.property_names);
final List<CharSequence> properties = new ArrayList<>(names.length);
mCursor = context.getContentResolver().query(mUri, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
final int indexName = mCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
if (indexName >= 0) {
properties.add(getProperty(null, names[0], mCursor.getString(indexName)));
}
final int indexSize = mCursor.getColumnIndex(OpenableColumns.SIZE);
if (indexSize >= 0) {
final long fileSize = Long.parseLong(mCursor.getString(indexSize));
properties.add(getProperty(null, names[0], fileName));
properties.add(getProperty(null, names[1], Utils.parseFileSize(fileSize)));
}
mCursor.close();
}
try {
final JSONObject json = new JSONObject(mProperties);
@ -89,9 +71,7 @@ public class DocumentPropertiesLoader extends AsyncTaskLoader<List<CharSequence>
@Override
public void deliverResult(List<CharSequence> properties) {
if (isReset()) {
onReleaseResources();
} else if (isStarted()) {
if (!isReset() && isStarted()) {
super.deliverResult(properties);
}
}
@ -106,26 +86,11 @@ public class DocumentPropertiesLoader extends AsyncTaskLoader<List<CharSequence>
cancelLoad();
}
@Override
public void onCanceled(List<CharSequence> properties) {
super.onCanceled(properties);
onReleaseResources();
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
onReleaseResources();
}
private void onReleaseResources() {
if (mCursor != null) {
mCursor.close();
mCursor = null;
}
}
private CharSequence getProperty(final JSONObject json, String name, String specName) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 372 B

View File

@ -1,30 +0,0 @@
<!--
Copyright (C) 2021 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="2.43375"
android:scaleY="2.43375"
android:translateX="24.795"
android:translateY="24.795">
<path
android:fillColor="#000000"
android:pathData="M18,4L6,4C4.9,4 4,4.9 4,6v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,6C20,4.9 19.1,4 18,4ZM9.5,11.5C9.5,12.33 8.83,13 8,13L7,13v1.25C7,14.66 6.66,15 6.25,15 5.84,15 5.5,14.66 5.5,14.25L5.5,10c0,-0.55 0.45,-1 1,-1L8,9c0.83,0 1.5,0.67 1.5,1.5zM14.5,13.5c0,0.83 -0.67,1.5 -1.5,1.5h-2c-0.28,0 -0.5,-0.22 -0.5,-0.5v-5C10.5,9.22 10.72,9 11,9h2c0.83,0 1.5,0.67 1.5,1.5zM18.5,9.75c0,0.41 -0.34,0.75 -0.75,0.75L17,10.5v1h0.75c0.41,0 0.75,0.34 0.75,0.75 0,0.41 -0.34,0.75 -0.75,0.75L17,13v1.25C17,14.66 16.66,15 16.25,15 15.84,15 15.5,14.66 15.5,14.25L15.5,10c0,-0.55 0.45,-1 1,-1h1.25c0.41,0 0.75,0.34 0.75,0.75zM7,11.5h1v-1L7,10.5ZM12,13.5h1v-3h-1z" />
</group>
</vector>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@ -19,12 +19,6 @@
android:title="@string/action_next"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_open"
android:icon="@drawable/ic_insert_drive_file_white_24dp"
android:title="@string/action_open"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_zoom_out"
android:icon="@drawable/ic_zoom_out_white_24dp"

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="strict" />

View File

@ -1,9 +0,0 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Customize your theme here. -->
<item name="android:windowBackground">#000000</item>
</style>
</resources>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@ -4,7 +4,6 @@
<!--<string name="action_settings">Settings</string>-->
<string name="action_previous">Previous page</string>
<string name="action_next">Next page</string>
<string name="action_open">Open document</string>
<string name="action_first">First page</string>
<string name="action_last">Last page</string>
<string name="action_zoom_out">Zoom out</string>

View File

@ -1,8 +0,0 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>