aboutsummaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorYuichi Araki <yaraki@google.com>2019-01-20 20:11:53 -0800
committerandroid-build-merger <android-build-merger@google.com>2019-01-20 20:11:53 -0800
commit278c1d5def726087a7431214a9ed15c6918f3a0f (patch)
tree4a4c7ff6c9811cbf4121ff8b7ceb1eaaec2801db /ui
parent47bb8f445917f90ad1d723e02ae567ea41c2e099 (diff)
parent9009018ee628628c02e1c266e601e52132782d50 (diff)
downloadandroid-278c1d5def726087a7431214a9ed15c6918f3a0f.tar.gz
PdfRendererBasic: Modernize the sample am: c87ea8c2ca
am: 9009018ee6 Change-Id: If04f160ef85682680b20968829b1a0ad12520107
Diffstat (limited to 'ui')
-rw-r--r--ui/graphics/PdfRendererBasic/Application/.gitignore16
-rw-r--r--ui/graphics/PdfRendererBasic/Application/build.gradle56
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicTest.java66
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.java62
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/AndroidManifest.xml23
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.java37
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.java258
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.java205
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/res/layout/main_activity.xml (renamed from ui/graphics/PdfRendererBasic/Application/src/main/res/layout/activity_main_real.xml)6
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/res/layout/pdf_renderer_basic_fragment.xml (renamed from ui/graphics/PdfRendererBasic/Application/src/main/res/layout/fragment_pdf_renderer_basic.xml)0
-rw-r--r--ui/graphics/PdfRendererBasic/Application/src/main/res/values/strings.xml2
-rw-r--r--ui/graphics/PdfRendererBasic/Application/tests/AndroidManifest.xml41
-rw-r--r--ui/graphics/PdfRendererBasic/Application/tests/src/com/example/android/pdfrendererbasic/tests/PdfRendererBasicFragmentTests.java132
-rw-r--r--ui/graphics/PdfRendererBasic/build.gradle21
-rw-r--r--ui/graphics/PdfRendererBasic/gradle.properties14
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/build.gradle46
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragmentTests.kt125
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.kt50
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/AndroidManifest.xml19
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.kt31
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.kt229
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.kt158
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/activity_main_real.xml23
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/main_activity.xml23
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/pdf_renderer_basic_fragment.xml (renamed from ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/fragment_pdf_renderer_basic.xml)23
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/values/strings.xml11
-rw-r--r--ui/graphics/PdfRendererBasic/kotlinApp/build.gradle19
-rw-r--r--ui/graphics/PdfRendererBasic/template-params.xml3
28 files changed, 844 insertions, 855 deletions
diff --git a/ui/graphics/PdfRendererBasic/Application/.gitignore b/ui/graphics/PdfRendererBasic/Application/.gitignore
deleted file mode 100644
index 6eb878d4..00000000
--- a/ui/graphics/PdfRendererBasic/Application/.gitignore
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2013 The Android Open Source Project
-#
-# 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.
-src/template/
-src/common/
-build.gradle
diff --git a/ui/graphics/PdfRendererBasic/Application/build.gradle b/ui/graphics/PdfRendererBasic/Application/build.gradle
new file mode 100644
index 00000000..fa47dfe9
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/Application/build.gradle
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+
+ defaultConfig {
+ applicationId 'com.example.android.pdfrendererbasic'
+ minSdkVersion 21
+ targetSdkVersion 28
+ versionCode 1
+ versionName '1.0'
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ testOptions {
+ unitTests {
+ returnDefaultValues = true
+ includeAndroidResources = true
+ }
+ }
+}
+
+dependencies {
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+
+ def lifecycle_version = '2.0.0'
+ implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
+ androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
+
+ testImplementation 'com.google.truth:truth:0.42'
+ testImplementation 'androidx.test:core:1.1.0'
+ testImplementation 'androidx.test:runner:1.1.1'
+ androidTestImplementation 'androidx.test.ext:truth:1.1.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+}
diff --git a/ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicTest.java b/ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicTest.java
new file mode 100644
index 00000000..105034b6
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.example.android.pdfrendererbasic;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.fragment.app.Fragment;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static com.google.common.truth.Truth.assertThat;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.core.AllOf.allOf;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PdfRendererBasicTest {
+
+ @Test
+ public void integration() {
+ final ActivityScenario<MainActivity> scenario = ActivityScenario.launch(MainActivity.class);
+ scenario.onActivity((activity) -> {
+ final Fragment fragment = activity.getSupportFragmentManager()
+ .findFragmentById(R.id.container);
+ assertThat(fragment).isInstanceOf(PdfRendererBasicFragment.class);
+ });
+ onView(withId(R.id.image)).check(matches(isDisplayed()));
+ onView(withId(R.id.previous)).check(matches(allOf(isDisplayed(), not(isEnabled()))));
+ onView(withId(R.id.next)).check(matches(allOf(isDisplayed(), isEnabled())));
+ onView(withText("PdfRendererBasic (1/10)")).check(matches(isDisplayed()));
+ onView(withId(R.id.next)).perform(click());
+ onView(withText("PdfRendererBasic (2/10)")).check(matches(isDisplayed()));
+ onView(withId(R.id.previous)).check(matches(allOf(isDisplayed(), isEnabled())));
+ onView(withId(R.id.next)).check(matches(allOf(isDisplayed(), isEnabled())));
+ for (int i = 0; i < 8; i++) {
+ onView(withId(R.id.next)).perform(click());
+ }
+ onView(withText("PdfRendererBasic (10/10)")).check(matches(isDisplayed()));
+ onView(withId(R.id.previous)).check(matches(allOf(isDisplayed(), isEnabled())));
+ onView(withId(R.id.next)).check(matches(allOf(isDisplayed(), not(isEnabled()))));
+ }
+
+}
diff --git a/ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.java b/ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.java
new file mode 100644
index 00000000..bd1d5d86
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.example.android.pdfrendererbasic;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class PdfRendererBasicViewModelTest {
+
+ @Rule
+ public final InstantTaskExecutorRule rule = new InstantTaskExecutorRule();
+
+ private PdfRendererBasicViewModel mViewModel = new PdfRendererBasicViewModel(
+ ApplicationProvider.getApplicationContext(), true);
+
+ @Test
+ public void allPages() {
+ assertThat(mViewModel).isNotNull();
+ final PdfRendererBasicViewModel.PageInfo firstInfo = mViewModel.getPageInfo().getValue();
+ assertThat(firstInfo).isNotNull();
+ assertThat(firstInfo.index).isEqualTo(0);
+ assertThat(firstInfo.count).isEqualTo(10);
+ assertThat(mViewModel.getPreviousEnabled().getValue()).isFalse();
+ assertThat(mViewModel.getNextEnabled().getValue()).isTrue();
+ assertThat(mViewModel.getPageBitmap().getValue()).isNotNull();
+ for (int i = 0; i < 9; i++) {
+ mViewModel.showNext();
+ }
+ final PdfRendererBasicViewModel.PageInfo lastInfo = mViewModel.getPageInfo().getValue();
+ assertThat(lastInfo).isNotNull();
+ assertThat(lastInfo.index).isEqualTo(9);
+ assertThat(lastInfo.count).isEqualTo(10);
+ assertThat(mViewModel.getPreviousEnabled().getValue()).isTrue();
+ assertThat(mViewModel.getNextEnabled().getValue()).isFalse();
+ assertThat(mViewModel.getPageBitmap().getValue()).isNotNull();
+ }
+
+}
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/AndroidManifest.xml b/ui/graphics/PdfRendererBasic/Application/src/main/AndroidManifest.xml
index 276c4bea..d320d211 100644
--- a/ui/graphics/PdfRendererBasic/Application/src/main/AndroidManifest.xml
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/AndroidManifest.xml
@@ -14,19 +14,21 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.example.android.pdfrendererbasic">
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.android.pdfrendererbasic"
- android:versionCode="1"
- android:versionName="1.0">
-
- <application android:allowBackup="true"
- android:label="@string/app_name"
+ <application
+ android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
- android:theme="@style/Theme.PdfRendererBasic">
+ android:label="@string/app_name"
+ android:theme="@style/Theme.PdfRendererBasic"
+ tools:ignore="GoogleAppIndexingWarning">
- <activity android:name=".MainActivity"
- android:label="@string/app_name">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -34,5 +36,4 @@
</activity>
</application>
-
</manifest>
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.java b/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.java
index 25781b79..0a59b7bb 100644
--- a/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.java
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.java
@@ -16,25 +16,29 @@
package com.example.android.pdfrendererbasic;
-import android.app.AlertDialog;
+import android.app.Dialog;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.DialogFragment;
+
public class MainActivity extends AppCompatActivity {
- public static final String FRAGMENT_PDF_RENDERER_BASIC = "pdf_renderer_basic";
+ private static final String FRAGMENT_INFO = "info";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main_real);
+ setContentView(R.layout.main_activity);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
- .add(R.id.container, new PdfRendererBasicFragment(),
- FRAGMENT_PDF_RENDERER_BASIC)
- .commit();
+ .add(R.id.container, new PdfRendererBasicFragment())
+ .commitNow();
}
}
@@ -48,12 +52,23 @@ public class MainActivity extends AppCompatActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_info:
- new AlertDialog.Builder(this)
- .setMessage(R.string.intro_message)
- .setPositiveButton(android.R.string.ok, null)
- .show();
+ new InfoDialogFragment().show(getSupportFragmentManager(), FRAGMENT_INFO);
return true;
}
return super.onOptionsItemSelected(item);
}
+
+ public static class InfoDialogFragment extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ return new AlertDialog.Builder(requireContext())
+ .setMessage(R.string.intro_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ }
+
+ }
+
}
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.java b/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.java
index 98f16941..2a933716 100644
--- a/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.java
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.java
@@ -16,235 +16,75 @@
package com.example.android.pdfrendererbasic;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.pdf.PdfRenderer;
+import android.app.Activity;
import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
-import android.widget.Toast;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.ViewModelProviders;
/**
- * This fragment has a big {@ImageView} that shows PDF pages, and 2
- * {@link android.widget.Button}s to move between pages. We use a
- * {@link android.graphics.pdf.PdfRenderer} to render PDF pages as
- * {@link android.graphics.Bitmap}s.
+ * This fragment has a big {@link ImageView} that shows PDF pages, and 2
+ * {@link android.widget.Button}s to move between pages.
*/
-public class PdfRendererBasicFragment extends Fragment implements View.OnClickListener {
+public class PdfRendererBasicFragment extends Fragment {
- /**
- * Key string for saving the state of current page index.
- */
- private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index";
+ private PdfRendererBasicViewModel mViewModel;
- /**
- * The filename of the PDF.
- */
- private static final String FILENAME = "sample.pdf";
-
- /**
- * File descriptor of the PDF.
- */
- private ParcelFileDescriptor mFileDescriptor;
-
- /**
- * {@link android.graphics.pdf.PdfRenderer} to render the PDF.
- */
- private PdfRenderer mPdfRenderer;
-
- /**
- * Page that is currently shown on the screen.
- */
- private PdfRenderer.Page mCurrentPage;
-
- /**
- * {@link android.widget.ImageView} that shows a PDF page as a {@link android.graphics.Bitmap}
- */
- private ImageView mImageView;
-
- /**
- * {@link android.widget.Button} to move to the previous page.
- */
- private Button mButtonPrevious;
-
- /**
- * {@link android.widget.Button} to move to the next page.
- */
- private Button mButtonNext;
-
- /**
- * PDF page index
- */
- private int mPageIndex;
-
- public PdfRendererBasicFragment() {
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- // Retain view references.
- mImageView = (ImageView) view.findViewById(R.id.image);
- mButtonPrevious = (Button) view.findViewById(R.id.previous);
- mButtonNext = (Button) view.findViewById(R.id.next);
- // Bind events.
- mButtonPrevious.setOnClickListener(this);
- mButtonNext.setOnClickListener(this);
-
- mPageIndex = 0;
- // If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
- if (null != savedInstanceState) {
- mPageIndex = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
- try {
- openRenderer(getActivity());
- showPage(mPageIndex);
- } catch (IOException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
- }
- }
-
- @Override
- public void onStop() {
- try {
- closeRenderer();
- } catch (IOException e) {
- e.printStackTrace();
+ private final View.OnClickListener mOnClickListener = (view) -> {
+ switch (view.getId()) {
+ case R.id.previous:
+ if (mViewModel != null) {
+ mViewModel.showPrevious();
+ }
+ break;
+ case R.id.next:
+ if (mViewModel != null) {
+ mViewModel.showNext();
+ }
+ break;
}
- super.onStop();
- }
+ };
@Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (null != mCurrentPage) {
- outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex());
- }
- }
-
- /**
- * Sets up a {@link android.graphics.pdf.PdfRenderer} and related resources.
- */
- private void openRenderer(Context context) throws IOException {
- // In this sample, we read a PDF from the assets directory.
- File file = new File(context.getCacheDir(), FILENAME);
- if (!file.exists()) {
- // Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
- // the cache directory.
- InputStream asset = context.getAssets().open(FILENAME);
- FileOutputStream output = new FileOutputStream(file);
- final byte[] buffer = new byte[1024];
- int size;
- while ((size = asset.read(buffer)) != -1) {
- output.write(buffer, 0, size);
- }
- asset.close();
- output.close();
- }
- mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
- // This is the PdfRenderer we use to render the PDF.
- if (mFileDescriptor != null) {
- mPdfRenderer = new PdfRenderer(mFileDescriptor);
- }
- }
-
- /**
- * Closes the {@link android.graphics.pdf.PdfRenderer} and related resources.
- *
- * @throws java.io.IOException When the PDF file cannot be closed.
- */
- private void closeRenderer() throws IOException {
- if (null != mCurrentPage) {
- mCurrentPage.close();
- }
- mPdfRenderer.close();
- mFileDescriptor.close();
- }
-
- /**
- * Shows the specified page of PDF to the screen.
- *
- * @param index The page index.
- */
- private void showPage(int index) {
- if (mPdfRenderer.getPageCount() <= index) {
- return;
- }
- // Make sure to close the current page before opening another one.
- if (null != mCurrentPage) {
- mCurrentPage.close();
- }
- // Use `openPage` to open a specific page in PDF.
- mCurrentPage = mPdfRenderer.openPage(index);
- // Important: the destination bitmap must be ARGB (not RGB).
- Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
- Bitmap.Config.ARGB_8888);
- // Here, we render the page onto the Bitmap.
- // To render a portion of the page, use the second and third parameter. Pass nulls to get
- // the default result.
- // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
- mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
- // We are ready to show the Bitmap to user.
- mImageView.setImageBitmap(bitmap);
- updateUi();
- }
-
- /**
- * Updates the state of 2 control buttons in response to the current page index.
- */
- private void updateUi() {
- int index = mCurrentPage.getIndex();
- int pageCount = mPdfRenderer.getPageCount();
- mButtonPrevious.setEnabled(0 != index);
- mButtonNext.setEnabled(index + 1 < pageCount);
- getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount));
- }
-
- /**
- * Gets the number of pages in the PDF. This method is marked as public for testing.
- *
- * @return The number of pages.
- */
- public int getPageCount() {
- return mPdfRenderer.getPageCount();
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.pdf_renderer_basic_fragment, container, false);
}
@Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.previous: {
- // Move to the previous page
- showPage(mCurrentPage.getIndex() - 1);
- break;
+ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
+ // View references.
+ final ImageView image = view.findViewById(R.id.image);
+ final Button buttonPrevious = view.findViewById(R.id.previous);
+ final Button buttonNext = view.findViewById(R.id.next);
+
+ // Bind data.
+ mViewModel = ViewModelProviders.of(this).get(PdfRendererBasicViewModel.class);
+ final LifecycleOwner viewLifecycleOwner = getViewLifecycleOwner();
+ mViewModel.getPageInfo().observe(viewLifecycleOwner, pageInfo -> {
+ if (pageInfo == null) {
+ return;
}
- case R.id.next: {
- // Move to the next page
- showPage(mCurrentPage.getIndex() + 1);
- break;
+ final Activity activity = getActivity();
+ if (activity != null) {
+ activity.setTitle(getString(R.string.app_name_with_index,
+ pageInfo.index + 1, pageInfo.count));
}
- }
+ });
+ mViewModel.getPageBitmap().observe(viewLifecycleOwner, image::setImageBitmap);
+ mViewModel.getPreviousEnabled().observe(viewLifecycleOwner, buttonPrevious::setEnabled);
+ mViewModel.getNextEnabled().observe(viewLifecycleOwner, buttonNext::setEnabled);
+
+ // Bind events.
+ buttonPrevious.setOnClickListener(mOnClickListener);
+ buttonNext.setOnClickListener(mOnClickListener);
}
}
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.java b/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.java
new file mode 100644
index 00000000..cb638c04
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.example.android.pdfrendererbasic;
+
+import android.app.Application;
+import android.graphics.Bitmap;
+import android.graphics.pdf.PdfRenderer;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import androidx.annotation.WorkerThread;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
+/**
+ * This holds all the data we need for this sample app.
+ * <p>
+ * We use a {@link android.graphics.pdf.PdfRenderer} to render PDF pages as
+ * {@link android.graphics.Bitmap}s.
+ */
+public class PdfRendererBasicViewModel extends AndroidViewModel {
+
+ private static final String TAG = "PdfRendererBasic";
+
+ /**
+ * The filename of the PDF.
+ */
+ private static final String FILENAME = "sample.pdf";
+
+ private final MutableLiveData<PageInfo> mPageInfo = new MutableLiveData<>();
+ private final MutableLiveData<Bitmap> mPageBitmap = new MutableLiveData<>();
+ private final MutableLiveData<Boolean> mPreviousEnabled = new MutableLiveData<>();
+ private final MutableLiveData<Boolean> mNextEnabled = new MutableLiveData<>();
+
+ private final Executor mExecutor;
+ private ParcelFileDescriptor mFileDescriptor;
+ private PdfRenderer mPdfRenderer;
+ private PdfRenderer.Page mCurrentPage;
+ private boolean mCleared;
+
+ @SuppressWarnings("unused")
+ public PdfRendererBasicViewModel(Application application) {
+ this(application, false);
+ }
+
+ PdfRendererBasicViewModel(Application application, boolean useInstantExecutor) {
+ super(application);
+ if (useInstantExecutor) {
+ mExecutor = Runnable::run;
+ } else {
+ mExecutor = Executors.newSingleThreadExecutor();
+ }
+ mExecutor.execute(() -> {
+ try {
+ openPdfRenderer();
+ showPage(0);
+ if (mCleared) {
+ closePdfRenderer();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to open PdfRenderer", e);
+ }
+ });
+ }
+
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ mExecutor.execute(() -> {
+ try {
+ closePdfRenderer();
+ mCleared = true;
+ } catch (IOException e) {
+ Log.i(TAG, "Failed to close PdfRenderer", e);
+ }
+ });
+ }
+
+ LiveData<PageInfo> getPageInfo() {
+ return mPageInfo;
+ }
+
+ LiveData<Bitmap> getPageBitmap() {
+ return mPageBitmap;
+ }
+
+ LiveData<Boolean> getPreviousEnabled() {
+ return mPreviousEnabled;
+ }
+
+ LiveData<Boolean> getNextEnabled() {
+ return mNextEnabled;
+ }
+
+ void showPrevious() {
+ if (mPdfRenderer == null || mCurrentPage == null) {
+ return;
+ }
+ final int index = mCurrentPage.getIndex();
+ if (index > 0) {
+ mExecutor.execute(() -> showPage(index - 1));
+ }
+ }
+
+ void showNext() {
+ if (mPdfRenderer == null || mCurrentPage == null) {
+ return;
+ }
+ final int index = mCurrentPage.getIndex();
+ if (index + 1 < mPdfRenderer.getPageCount()) {
+ mExecutor.execute(() -> showPage(index + 1));
+ }
+ }
+
+ @WorkerThread
+ private void openPdfRenderer() throws IOException {
+ final File file = new File(getApplication().getCacheDir(), FILENAME);
+ if (!file.exists()) {
+ // Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
+ // the cache directory.
+ final InputStream asset = getApplication().getAssets().open(FILENAME);
+ final FileOutputStream output = new FileOutputStream(file);
+ final byte[] buffer = new byte[1024];
+ int size;
+ while ((size = asset.read(buffer)) != -1) {
+ output.write(buffer, 0, size);
+ }
+ asset.close();
+ output.close();
+ }
+ mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+ if (mFileDescriptor != null) {
+ mPdfRenderer = new PdfRenderer(mFileDescriptor);
+ }
+ }
+
+ @WorkerThread
+ private void closePdfRenderer() throws IOException {
+ if (mCurrentPage != null) {
+ mCurrentPage.close();
+ }
+ if (mPdfRenderer != null) {
+ mPdfRenderer.close();
+ }
+ if (mFileDescriptor != null) {
+ mFileDescriptor.close();
+ }
+ }
+
+ @WorkerThread
+ private void showPage(int index) {
+ // Make sure to close the current page before opening another one.
+ if (null != mCurrentPage) {
+ mCurrentPage.close();
+ }
+ // Use `openPage` to open a specific page in PDF.
+ mCurrentPage = mPdfRenderer.openPage(index);
+ // Important: the destination bitmap must be ARGB (not RGB).
+ final Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ // Here, we render the page onto the Bitmap.
+ // To render a portion of the page, use the second and third parameter. Pass nulls to get
+ // the default result.
+ // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
+ mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
+ mPageBitmap.postValue(bitmap);
+ final int count = mPdfRenderer.getPageCount();
+ mPageInfo.postValue(new PageInfo(index, count));
+ mPreviousEnabled.postValue(index > 0);
+ mNextEnabled.postValue(index + 1 < count);
+ }
+
+ static class PageInfo {
+ final int index;
+ final int count;
+
+ PageInfo(int index, int count) {
+ this.index = index;
+ this.count = count;
+ }
+ }
+
+}
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/activity_main_real.xml b/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/main_activity.xml
index dcd52bea..60a42be2 100644
--- a/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/activity_main_real.xml
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/main_activity.xml
@@ -14,10 +14,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity"
- tools:ignore="MergeRootFrame" />
+ tools:context=".MainActivity" />
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/fragment_pdf_renderer_basic.xml b/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/pdf_renderer_basic_fragment.xml
index 7ecfac36..7ecfac36 100644
--- a/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/fragment_pdf_renderer_basic.xml
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/res/layout/pdf_renderer_basic_fragment.xml
diff --git a/ui/graphics/PdfRendererBasic/Application/src/main/res/values/strings.xml b/ui/graphics/PdfRendererBasic/Application/src/main/res/values/strings.xml
index e0182fd3..995a82e9 100644
--- a/ui/graphics/PdfRendererBasic/Application/src/main/res/values/strings.xml
+++ b/ui/graphics/PdfRendererBasic/Application/src/main/res/values/strings.xml
@@ -16,7 +16,9 @@
-->
<resources>
+ <string name="app_name">PdfRendererBasic</string>
<string name="app_name_with_index">PdfRendererBasic (%1$d/%2$d)</string>
+ <string name="intro_message">This sample demonstrates how to use PdfRenderer to display PDF documents on the screen.</string>
<string name="info">Info</string>
<string name="previous">Previous</string>
<string name="next">Next</string>
diff --git a/ui/graphics/PdfRendererBasic/Application/tests/AndroidManifest.xml b/ui/graphics/PdfRendererBasic/Application/tests/AndroidManifest.xml
deleted file mode 100644
index 54829c78..00000000
--- a/ui/graphics/PdfRendererBasic/Application/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 The Android Open Source Project
-
- 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.
- -->
-<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
-<manifest
- package="com.example.android.pdfrendererbasic.tests"
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:versionCode="1"
- android:versionName="1.0">
-
- <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
-
- <!-- We add an application tag here just so that we can indicate that
- this package needs to link against the android.test library,
- which is needed when building test cases. -->
- <application>
- <uses-library android:name="android.test.runner"/>
- </application>
-
- <!--
- Specifies the instrumentation test runner used to run the tests.
- -->
- <instrumentation
- android:name="android.test.InstrumentationTestRunner"
- android:label="Tests for com.example.android.pdfrendererbasic"
- android:targetPackage="com.example.android.pdfrendererbasic"/>
-
-</manifest>
diff --git a/ui/graphics/PdfRendererBasic/Application/tests/src/com/example/android/pdfrendererbasic/tests/PdfRendererBasicFragmentTests.java b/ui/graphics/PdfRendererBasic/Application/tests/src/com/example/android/pdfrendererbasic/tests/PdfRendererBasicFragmentTests.java
deleted file mode 100644
index 0f94cbf8..00000000
--- a/ui/graphics/PdfRendererBasic/Application/tests/src/com/example/android/pdfrendererbasic/tests/PdfRendererBasicFragmentTests.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * 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.
- */
-
-package com.example.android.pdfrendererbasic.tests;
-
-import android.content.pm.ActivityInfo;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.View;
-import android.widget.Button;
-
-import com.example.android.pdfrendererbasic.MainActivity;
-import com.example.android.pdfrendererbasic.PdfRendererBasicFragment;
-import com.example.android.pdfrendererbasic.R;
-
-/**
- * Tests for PdfRendererBasic sample.
- */
-public class PdfRendererBasicFragmentTests extends ActivityInstrumentationTestCase2<MainActivity> {
-
- private MainActivity mActivity;
- private PdfRendererBasicFragment mFragment;
-
- private Button mButtonPrevious;
- private Button mButtonNext;
-
- public PdfRendererBasicFragmentTests() {
- super(MainActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- mFragment = (PdfRendererBasicFragment) mActivity.getFragmentManager()
- .findFragmentByTag(MainActivity.FRAGMENT_PDF_RENDERER_BASIC);
- }
-
- @LargeTest
- public void testActivityTitle() {
- // The title of the activity should be "PdfRendererBasic (1/10)" at first
- String expectedActivityTitle = mActivity.getString(R.string.app_name_with_index, 1,
- mFragment.getPageCount());
- assertEquals(expectedActivityTitle, mActivity.getTitle());
- }
-
- @LargeTest
- public void testButtons_previousDisabledAtFirst() {
- setUpButtons();
- // Check that the previous button is disabled at first
- assertFalse(mButtonPrevious.isEnabled());
- // The next button should be enabled
- assertTrue(mButtonNext.isEnabled());
- }
-
- @LargeTest
- public void testButtons_bothEnabledInMiddle() {
- setUpButtons();
- turnPages(1);
- // Two buttons should be both enabled
- assertTrue(mButtonPrevious.isEnabled());
- assertTrue(mButtonNext.isEnabled());
- }
-
- @LargeTest
- public void testButtons_nextDisabledLastPage() {
- setUpButtons();
- int pageCount = mFragment.getPageCount();
- // Click till it reaches the last page
- turnPages(pageCount - 1);
- // Check the page count
- String expectedActivityTitle = mActivity.getString(R.string.app_name_with_index,
- pageCount, pageCount);
- assertEquals(expectedActivityTitle, mActivity.getTitle());
- // The previous button should be enabled
- assertTrue(mButtonPrevious.isEnabled());
- // Check that the next button is disabled
- assertFalse(mButtonNext.isEnabled());
- }
-
- @LargeTest
- public void testOrientationChangePreserveState() {
- mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- setUpButtons();
- turnPages(1);
- int pageCount = mFragment.getPageCount();
- String expectedActivityTitle = mActivity.getString(R.string.app_name_with_index,
- 2, pageCount);
- assertEquals(expectedActivityTitle, mActivity.getTitle());
- mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- // Check that the title is the same after orientation change
- assertEquals(expectedActivityTitle, mActivity.getTitle());
- }
-
- /**
- * Prepares references to the buttons "Previous" and "Next".
- */
- private void setUpButtons() {
- View view = mFragment.getView();
- assertNotNull(view);
- mButtonPrevious = (Button) view.findViewById(R.id.previous);
- assertNotNull(mButtonPrevious);
- mButtonNext = (Button) view.findViewById(R.id.next);
- assertNotNull(mButtonNext);
- }
-
- /**
- * Click the "Next" button to turn the pages.
- *
- * @param count The number of times to turn pages.
- */
- private void turnPages(int count) {
- for (int i = 0; i < count; ++i) {
- TouchUtils.clickView(this, mButtonNext);
- }
- }
-
-}
diff --git a/ui/graphics/PdfRendererBasic/build.gradle b/ui/graphics/PdfRendererBasic/build.gradle
index be1fa823..93ddf8c4 100644
--- a/ui/graphics/PdfRendererBasic/build.gradle
+++ b/ui/graphics/PdfRendererBasic/build.gradle
@@ -1,14 +1,29 @@
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.3.0'
+ }
+}
-
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
// BEGIN_EXCLUDE
import com.example.android.samples.build.SampleGenPlugin
+
apply plugin: SampleGenPlugin
samplegen {
- pathToBuild "../../../../../build"
- pathToSamplesCommon "../../../common"
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
}
apply from: "../../../../../build/build.gradle"
// END_EXCLUDE
diff --git a/ui/graphics/PdfRendererBasic/gradle.properties b/ui/graphics/PdfRendererBasic/gradle.properties
new file mode 100644
index 00000000..795e261a
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/gradle.properties
@@ -0,0 +1,14 @@
+# Project-wide Gradle settings.
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+org.gradle.parallel=true
+
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/build.gradle b/ui/graphics/PdfRendererBasic/kotlinApp/Application/build.gradle
index 44d34d58..a1be48c4 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/build.gradle
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/build.gradle
@@ -1,35 +1,39 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
android {
- compileSdkVersion rootProject.ext.compileSdkVersion
+ compileSdkVersion 28
+
defaultConfig {
- applicationId "com.example.android.pdfrendererbasic"
- minSdkVersion rootProject.ext.minSdkVersion
- targetSdkVersion rootProject.ext.targetSdkVersion
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ applicationId 'com.example.android.pdfrendererbasic'
+ minSdkVersion 21
+ targetSdkVersion 28
versionCode 1
- versionName "1.0"
+ versionName '1.0'
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+
+ testOptions {
+ unitTests {
+ returnDefaultValues = true
+ includeAndroidResources = true
}
}
}
dependencies {
- implementation "com.android.support:appcompat-v7:$rootProject.ext.supportLibVersion"
- implementation "com.android.support:support-v4:$rootProject.ext.supportLibVersion"
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.ext.kotlinVersion"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0'
+
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+
+ def lifecycle_version = '2.0.0'
+ implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
+ androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
- // Testing dependencies
- androidTestImplementation "com.android.support.test.espresso:espresso-contrib:$rootProject.ext.espressoVersion"
- androidTestImplementation "com.android.support.test.espresso:espresso-core:$rootProject.ext.espressoVersion"
- androidTestCompile "com.android.support:support-annotations:$rootProject.ext.supportLibVersion"
- androidTestCompile "com.android.support.test:runner:$rootProject.ext.supportTestVersion"
- androidTestCompile "com.android.support.test:rules:$rootProject.ext.supportTestVersion"
- testImplementation "junit:junit:$rootProject.ext.junitVersion"
+ testImplementation 'com.google.truth:truth:0.42'
+ testImplementation 'androidx.test:core:1.1.0'
+ testImplementation 'androidx.test:runner:1.1.1'
+ androidTestImplementation 'androidx.test.ext:truth:1.1.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragmentTests.kt b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragmentTests.kt
deleted file mode 100644
index b2abc69b..00000000
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragmentTests.kt
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * 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.
- */
-
-package com.example.android.pdfrendererbasic
-
-import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
-import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
-import android.support.test.espresso.Espresso.onView
-import android.support.test.espresso.action.ViewActions.click
-import android.support.test.espresso.matcher.ViewMatchers.withId
-import android.support.test.rule.ActivityTestRule
-import android.support.test.runner.AndroidJUnit4
-import android.widget.Button
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Tests for PdfRendererBasic sample.
- */
-@RunWith(AndroidJUnit4::class)
-class PdfRendererBasicFragmentTests {
-
- private lateinit var fragment: PdfRendererBasicFragment
- private lateinit var btnPrevious: Button
- private lateinit var btnNext: Button
-
- @Rule @JvmField
- val activityTestRule = ActivityTestRule(MainActivity::class.java)
-
- @Before fun before() {
- activityTestRule.activity.supportFragmentManager.beginTransaction()
- fragment = activityTestRule.activity.supportFragmentManager
- .findFragmentByTag(FRAGMENT_PDF_RENDERER_BASIC) as PdfRendererBasicFragment
- }
-
- @Test fun testActivityTitle() {
- // The title of the activity should be "PdfRendererBasic (1/10)" at first
- val expectedActivityTitle = activityTestRule.activity.getString(
- R.string.app_name_with_index, 1, fragment.getPageCount())
- assertEquals(expectedActivityTitle, activityTestRule.activity.title)
- }
-
- @Test fun testButtons_previousDisabledAtFirst() {
- setUpButtons()
- // Check that the previous button is disabled at first
- assertFalse(btnPrevious.isEnabled)
- // The next button should be enabled
- assertTrue(btnNext.isEnabled)
- }
-
- @Test fun testButtons_bothEnabledInMiddle() {
- setUpButtons()
- turnPages(1)
- // Two buttons should be both enabled
- assertTrue(btnPrevious.isEnabled)
- assertTrue(btnNext.isEnabled)
- }
-
- @Test fun testButtons_nextDisabledLastPage() {
- setUpButtons()
- val pageCount = fragment.getPageCount()
- // Click till it reaches the last page
- turnPages(pageCount - 1)
- // Check the page count
- val expectedActivityTitle = activityTestRule.activity.getString(
- R.string.app_name_with_index, pageCount, pageCount)
- assertEquals(expectedActivityTitle, activityTestRule.activity.title)
- // The previous button should be enabled
- assertTrue(btnPrevious.isEnabled)
- // Check that the next button is disabled
- assertFalse(btnNext.isEnabled)
- }
-
- @Test fun testOrientationChangePreserveState() {
- activityTestRule.activity.requestedOrientation = SCREEN_ORIENTATION_PORTRAIT
- setUpButtons()
- turnPages(1)
- val pageCount = fragment.getPageCount()
- val expectedActivityTitle = activityTestRule.activity
- .getString(R.string.app_name_with_index, 2, pageCount)
- assertEquals(expectedActivityTitle, activityTestRule.activity.title)
- activityTestRule.activity.requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE
- // Check that the title is the same after orientation change
- assertEquals(expectedActivityTitle, activityTestRule.activity.title)
- }
-
- /**
- * Prepares references to the buttons "Previous" and "Next".
- */
- private fun setUpButtons() {
- val view = fragment.view ?: return
- btnPrevious = view.findViewById(R.id.previous)
- btnNext = view.findViewById(R.id.next)
- }
-
- /**
- * Click the "Next" button to turn the pages.
- *
- * @param count The number of times to turn pages.
- */
- private fun turnPages(count: Int) {
- for (i in 0 until count) {
- onView(withId(R.id.next)).perform(click())
- }
- }
-
-}
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.kt b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.kt
new file mode 100644
index 00000000..c2d7b26a
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/androidTest/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModelTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.example.android.pdfrendererbasic
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.runner.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class PdfRendererBasicViewModelTest {
+
+ @get:Rule
+ val instantTaskExecutorRule = InstantTaskExecutorRule()
+
+ private val viewModel = PdfRendererBasicViewModel(
+ ApplicationProvider.getApplicationContext(), true)
+
+ @Test
+ fun allPages() {
+ assertThat(viewModel).isNotNull()
+ assertThat(viewModel.pageInfo.value).isEqualTo(0 to 10)
+ assertThat(viewModel.previousEnabled.value).isFalse()
+ assertThat(viewModel.nextEnabled.value).isTrue()
+ assertThat(viewModel.pageBitmap.value).isNotNull()
+ repeat(9) { viewModel.showNext() }
+ assertThat(viewModel.pageInfo.value).isEqualTo(9 to 10)
+ assertThat(viewModel.previousEnabled.value).isTrue()
+ assertThat(viewModel.nextEnabled.value).isFalse()
+ assertThat(viewModel.pageBitmap.value).isNotNull()
+ }
+
+}
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/AndroidManifest.xml b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/AndroidManifest.xml
index de585c9c..22500853 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/AndroidManifest.xml
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/AndroidManifest.xml
@@ -14,17 +14,21 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.example.android.pdfrendererbasic">
- <application android:allowBackup="false"
- android:label="@string/app_name"
+ <application
+ android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
- android:theme="@style/Theme.PdfRendererBasic">
+ android:label="@string/app_name"
+ android:theme="@style/Theme.PdfRendererBasic"
+ tools:ignore="GoogleAppIndexingWarning">
- <activity android:name=".MainActivity"
- android:label="@string/app_name">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -32,5 +36,4 @@
</activity>
</application>
-
</manifest>
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.kt b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.kt
index 1d253bd1..dd0ffc59 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.kt
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/MainActivity.kt
@@ -16,24 +16,27 @@
package com.example.android.pdfrendererbasic
-import android.app.AlertDialog
+import android.app.Dialog
import android.os.Bundle
-import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
-
-val FRAGMENT_PDF_RENDERER_BASIC = "pdf_renderer_basic"
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.DialogFragment
class MainActivity : AppCompatActivity() {
+ companion object {
+ const val FRAGMENT_INFO = "info"
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main_real)
+ setContentView(R.layout.main_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
- .add(R.id.container, PdfRendererBasicFragment(), FRAGMENT_PDF_RENDERER_BASIC)
- .commit()
+ .replace(R.id.container, PdfRendererBasicFragment())
+ .commitNow()
}
}
@@ -45,14 +48,20 @@ class MainActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_info -> {
- AlertDialog.Builder(this)
- .setMessage(R.string.intro_message)
- .setPositiveButton(android.R.string.ok, null)
- .show()
+ InfoFragment().show(supportFragmentManager, FRAGMENT_INFO)
return true
}
else -> super.onOptionsItemSelected(item)
}
}
+ class InfoFragment : DialogFragment() {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ return AlertDialog.Builder(requireContext())
+ .setMessage(R.string.intro_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .show()
+ }
+ }
+
}
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.kt b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.kt
index 89e1cfd0..1ffc5817 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.kt
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicFragment.kt
@@ -16,222 +16,47 @@
package com.example.android.pdfrendererbasic
-import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.Bitmap.createBitmap
-import android.graphics.pdf.PdfRenderer
import android.os.Bundle
-import android.os.ParcelFileDescriptor
-import android.support.v4.app.Fragment
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
-import java.io.File
-import java.io.FileOutputStream
-import java.io.IOException
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
/**
* This fragment has a big [ImageView] that shows PDF pages, and 2 [Button]s to move between pages.
- * We use a [PdfRenderer] to render PDF pages as [Bitmap]s.
*/
-class PdfRendererBasicFragment : Fragment(), View.OnClickListener {
+class PdfRendererBasicFragment : Fragment() {
- /**
- * The filename of the PDF.
- */
- private val FILENAME = "sample.pdf"
-
- /**
- * Key string for saving the state of current page index.
- */
- private val STATE_CURRENT_PAGE_INDEX = "current_page_index"
-
- /**
- * String for logging.
- */
- private val TAG = "PdfRendererBasicFragment"
-
- /**
- * The initial page index of the PDF.
- */
- private val INITIAL_PAGE_INDEX = 0
-
- /**
- * File descriptor of the PDF.
- */
- private lateinit var fileDescriptor: ParcelFileDescriptor
-
- /**
- * [PdfRenderer] to render the PDF.
- */
- private lateinit var pdfRenderer: PdfRenderer
-
- /**
- * Page that is currently shown on the screen.
- */
- private lateinit var currentPage: PdfRenderer.Page
-
- /**
- * [ImageView] that shows a PDF page as a [Bitmap].
- */
- private lateinit var imageView: ImageView
-
- /**
- * [Button] to move to the previous page.
- */
- private lateinit var btnPrevious: Button
-
- /**
- * [Button] to move to the next page.
- */
- private lateinit var btnNext: Button
-
- /**
- * PDF page index.
- */
- private var pageIndex: Int = INITIAL_PAGE_INDEX
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false)
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.pdf_renderer_basic_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- imageView = view.findViewById(R.id.image)
- btnPrevious = view.findViewById<Button>(R.id.previous).also { it.setOnClickListener(this) }
- btnNext = view.findViewById<Button>(R.id.next).also { it.setOnClickListener(this)}
-
- // If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
- if (savedInstanceState != null) {
- pageIndex = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, INITIAL_PAGE_INDEX)
- } else {
- pageIndex = INITIAL_PAGE_INDEX
- }
- }
-
- override fun onStart() {
- super.onStart()
- try {
- openRenderer(activity)
- showPage(pageIndex)
- } catch (e: IOException) {
- Log.d(TAG, e.toString())
- }
- }
-
- override fun onStop() {
- try {
- closeRenderer()
- } catch (e: IOException) {
- Log.d(TAG, e.toString())
- }
- super.onStop()
- }
-
- override fun onSaveInstanceState(outState: Bundle) {
- outState.putInt(STATE_CURRENT_PAGE_INDEX, currentPage.index)
- super.onSaveInstanceState(outState)
- }
-
- /**
- * Sets up a [PdfRenderer] and related resources.
- */
- @Throws(IOException::class)
- private fun openRenderer(context: Context?) {
- if (context == null) return
-
- // In this sample, we read a PDF from the assets directory.
- val file = File(context.cacheDir, FILENAME)
- if (!file.exists()) {
- // Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
- // the cache directory.
- val asset = context.assets.open(FILENAME)
- val output = FileOutputStream(file)
- val buffer = ByteArray(1024)
- var size = asset.read(buffer)
- while (size != -1) {
- output.write(buffer, 0, size)
- size = asset.read(buffer)
- }
- asset.close()
- output.close()
- }
- fileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
- // This is the PdfRenderer we use to render the PDF.
- pdfRenderer = PdfRenderer(fileDescriptor)
- currentPage = pdfRenderer.openPage(pageIndex)
- }
-
- /**
- * Closes the [PdfRenderer] and related resources.
- *
- * @throws IOException When the PDF file cannot be closed.
- */
- @Throws(IOException::class)
- private fun closeRenderer() {
- currentPage.close()
- pdfRenderer.close()
- fileDescriptor.close()
- }
-
- /**
- * Shows the specified page of PDF to the screen.
- *
- * @param index The page index.
- */
- private fun showPage(index: Int) {
- if (pdfRenderer.pageCount <= index) return
-
- // Make sure to close the current page before opening another one.
- currentPage.close()
- // Use `openPage` to open a specific page in PDF.
- currentPage = pdfRenderer.openPage(index)
- // Important: the destination bitmap must be ARGB (not RGB).
- val bitmap = createBitmap(currentPage.width, currentPage.height, Bitmap.Config.ARGB_8888)
- // Here, we render the page onto the Bitmap.
- // To render a portion of the page, use the second and third parameter. Pass nulls to get
- // the default result.
- // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
- currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
- // We are ready to show the Bitmap to user.
- imageView.setImageBitmap(bitmap)
- updateUi()
- }
-
- /**
- * Updates the state of 2 control buttons in response to the current page index.
- */
- private fun updateUi() {
- val index = currentPage.index
- val pageCount = pdfRenderer.pageCount
- btnPrevious.isEnabled = (0 != index)
- btnNext.isEnabled = (index + 1 < pageCount)
- activity?.title = getString(R.string.app_name_with_index, index + 1, pageCount)
- }
-
- /**
- * Returns the page count of of the PDF.
- */
- fun getPageCount() = pdfRenderer.pageCount
-
- override fun onClick(view: View) {
- when (view.id) {
- R.id.previous -> {
- // Move to the previous page/
- showPage(currentPage.index - 1)
- }
- R.id.next -> {
- // Move to the next page.
- showPage(currentPage.index + 1)
- }
- }
+ // View references.
+ val image: ImageView = view.findViewById(R.id.image)
+ val buttonPrevious: Button = view.findViewById(R.id.previous)
+ val buttonNext: Button = view.findViewById(R.id.next)
+
+ // Bind data.
+ val viewModel = ViewModelProviders.of(this).get(PdfRendererBasicViewModel::class.java)
+ viewModel.pageInfo.observe(viewLifecycleOwner, Observer { (index, count) ->
+ activity?.title = getString(R.string.app_name_with_index, index + 1, count)
+ })
+ viewModel.pageBitmap.observe(viewLifecycleOwner, Observer { image.setImageBitmap(it) })
+ viewModel.previousEnabled.observe(viewLifecycleOwner, Observer {
+ buttonPrevious.isEnabled = it
+ })
+ viewModel.nextEnabled.observe(viewLifecycleOwner, Observer {
+ buttonNext.isEnabled = it
+ })
+
+ // Bind events.
+ buttonPrevious.setOnClickListener { viewModel.showPrevious() }
+ buttonNext.setOnClickListener { viewModel.showNext() }
}
}
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.kt b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.kt
new file mode 100644
index 00000000..6324cce3
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/java/com/example/android/pdfrendererbasic/PdfRendererBasicViewModel.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.example.android.pdfrendererbasic
+
+import android.app.Application
+import android.graphics.Bitmap
+import android.graphics.pdf.PdfRenderer
+import android.os.ParcelFileDescriptor
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.launch
+import java.io.File
+import java.util.concurrent.Executor
+import java.util.concurrent.Executors
+
+class PdfRendererBasicViewModel @JvmOverloads constructor(
+ application: Application,
+ useInstantExecutor: Boolean = false
+) : AndroidViewModel(application) {
+
+ companion object {
+ const val FILENAME = "sample.pdf"
+ }
+
+ private val job = Job()
+ private val executor = if (useInstantExecutor) {
+ Executor { it.run() }
+ } else {
+ Executors.newSingleThreadExecutor()
+ }
+ private val scope = CoroutineScope(executor.asCoroutineDispatcher() + job)
+
+ private var fileDescriptor: ParcelFileDescriptor? = null
+ private var pdfRenderer: PdfRenderer? = null
+ private var currentPage: PdfRenderer.Page? = null
+ private var cleared = false
+
+ private val _pageBitmap = MutableLiveData<Bitmap>()
+ val pageBitmap: LiveData<Bitmap>
+ get() = _pageBitmap
+
+ private val _previousEnabled = MutableLiveData<Boolean>()
+ val previousEnabled: LiveData<Boolean>
+ get() = _previousEnabled
+
+ private val _nextEnabled = MutableLiveData<Boolean>()
+ val nextEnabled: LiveData<Boolean>
+ get() = _nextEnabled
+
+ private val _pageInfo = MutableLiveData<Pair<Int, Int>>()
+ val pageInfo: LiveData<Pair<Int, Int>>
+ get() = _pageInfo
+
+ init {
+ scope.launch {
+ openPdfRenderer()
+ showPage(0)
+ if (cleared) {
+ closePdfRenderer()
+ }
+ }
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ scope.launch {
+ closePdfRenderer()
+ cleared = true
+ job.cancel()
+ }
+ }
+
+ fun showPrevious() {
+ scope.launch {
+ currentPage?.let { page ->
+ if (page.index > 0) {
+ showPage(page.index - 1)
+ }
+ }
+ }
+ }
+
+ fun showNext() {
+ scope.launch {
+ pdfRenderer?.let { renderer ->
+ currentPage?.let { page ->
+ if (page.index + 1 < renderer.pageCount) {
+ showPage(page.index + 1)
+ }
+ }
+ }
+ }
+ }
+
+ private fun openPdfRenderer() {
+ val application = getApplication<Application>()
+ val file = File(application.cacheDir, FILENAME)
+ if (!file.exists()) {
+ application.assets.open(FILENAME).use { asset ->
+ file.writeBytes(asset.readBytes())
+ }
+ }
+ fileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY).also {
+ pdfRenderer = PdfRenderer(it)
+ }
+ }
+
+ private fun showPage(index: Int) {
+ // Make sure to close the current page before opening another one.
+ currentPage?.let { page ->
+ currentPage = null
+ page.close()
+ }
+ pdfRenderer?.let { renderer ->
+ // Use `openPage` to open a specific page in PDF.
+ val page = renderer.openPage(index).also {
+ currentPage = it
+ }
+ // Important: the destination bitmap must be ARGB (not RGB).
+ val bitmap = Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
+ // Here, we render the page onto the Bitmap.
+ // To render a portion of the page, use the second and third parameter. Pass nulls to get
+ // the default result.
+ // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
+ page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
+ _pageBitmap.postValue(bitmap)
+ val count = renderer.pageCount
+ _pageInfo.postValue(index to count)
+ _previousEnabled.postValue(index > 0)
+ _nextEnabled.postValue(index + 1 < count)
+ }
+ }
+
+ private fun closePdfRenderer() {
+ currentPage?.close()
+ pdfRenderer?.close()
+ fileDescriptor?.close()
+ }
+
+}
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/activity_main_real.xml b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/activity_main_real.xml
deleted file mode 100644
index 5d130ff5..00000000
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/activity_main_real.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright 2017 The Android Open Source Project
-
- 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.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity"
- tools:ignore="MergeRootFrame" />
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/main_activity.xml b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/main_activity.xml
new file mode 100644
index 00000000..a613a72c
--- /dev/null
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/main_activity.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ 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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity" />
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/fragment_pdf_renderer_basic.xml b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/pdf_renderer_basic_fragment.xml
index aa8a9e1a..719502ed 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/fragment_pdf_renderer_basic.xml
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/layout/pdf_renderer_basic_fragment.xml
@@ -1,18 +1,18 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017 The Android Open Source Project
+ Copyright (C) 2017 The Android Open Source Project
- 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
+ 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
+ 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.
+ 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
@@ -52,7 +52,6 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/next" />
-
</LinearLayout>
</LinearLayout>
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/values/strings.xml b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/values/strings.xml
index 55f04f91..04968e4d 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/values/strings.xml
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/Application/src/main/res/values/strings.xml
@@ -15,19 +15,10 @@
limitations under the License.
-->
<resources>
-
<string name="app_name">PdfRendererBasic</string>
<string name="app_name_with_index">PdfRendererBasic (%1$d/%2$d)</string>
<string name="info">Info</string>
<string name="previous">Previous</string>
<string name="next">Next</string>
- <string name="intro_message">
- <![CDATA[
-
-
- This sample demonstrates how to use PdfRenderer to display PDF documents on the screen.
-
-
- ]]>
- </string>
+ <string name="intro_message">This sample demonstrates how to use PdfRenderer to display PDF documents on the screen</string>
</resources>
diff --git a/ui/graphics/PdfRendererBasic/kotlinApp/build.gradle b/ui/graphics/PdfRendererBasic/kotlinApp/build.gradle
index daa90118..4086415a 100644
--- a/ui/graphics/PdfRendererBasic/kotlinApp/build.gradle
+++ b/ui/graphics/PdfRendererBasic/kotlinApp/build.gradle
@@ -1,22 +1,13 @@
buildscript {
- ext {
- compileSdkVersion = 27
- minSdkVersion = 24
- targetSdkVersion = 27
-
- espressoVersion = '3.0.1'
- junitVersion = '4.12'
- kotlinVersion = '1.3.11'
- supportLibVersion = '27.0.2'
- supportTestVersion = '1.0.1'
- }
+ ext.kotlin_version = '1.3.11'
repositories {
google()
jcenter()
}
+
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@@ -26,7 +17,3 @@ allprojects {
jcenter()
}
}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
diff --git a/ui/graphics/PdfRendererBasic/template-params.xml b/ui/graphics/PdfRendererBasic/template-params.xml
index 81ea8268..3d79c17e 100644
--- a/ui/graphics/PdfRendererBasic/template-params.xml
+++ b/ui/graphics/PdfRendererBasic/template-params.xml
@@ -33,7 +33,8 @@
</intro>
</strings>
- <template src="base"/>
+ <template src="base-build"/>
+ <androidX>true</androidX>
<metadata>
<status>PUBLISHED</status>