summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-03-30 17:50:36 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-03-31 13:00:41 +0200
commitf8b35b0fe546c9f34626155f19dafe16a8f82829 (patch)
treeceb16a90ea3dcdb5a3adad6da58c11fb8e54f522
parentd68576c3785572c1f5d41f83015b8fe6bbcbe9e8 (diff)
downloadmupdf-f8b35b0fe546c9f34626155f19dafe16a8f82829.tar.xz
android: Add new example viewer.
Thanks to Fred Ross-Perry.
-rw-r--r--platform/android/example/README12
-rw-r--r--platform/android/example/app/build.gradle46
-rw-r--r--platform/android/example/app/proguard-rules.pro17
-rw-r--r--platform/android/example/app/src/main/AndroidManifest.xml46
-rw-r--r--platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocActivity.java228
-rw-r--r--platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocAdapter.java76
-rw-r--r--platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocItem.java17
-rw-r--r--platform/android/example/app/src/main/java/com/artifex/mupdf/example/DocViewActivity.java105
-rw-r--r--platform/android/example/app/src/main/java/com/artifex/mupdf/example/MainActivity.java20
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_any.pngbin0 -> 3167 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_fldr.pngbin0 -> 1523 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_up.pngbin0 -> 2016 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_any.pngbin0 -> 1744 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_fldr.pngbin0 -> 834 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_up.pngbin0 -> 821 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_any.pngbin0 -> 4846 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_fldr.pngbin0 -> 2153 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_up.pngbin0 -> 2420 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_any.pngbin0 -> 9123 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_fldr.pngbin0 -> 4075 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_up.pngbin0 -> 4613 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_any.pngbin0 -> 14341 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_fldr.pngbin0 -> 6189 bytes
-rwxr-xr-xplatform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_up.pngbin0 -> 7804 bytes
-rw-r--r--platform/android/example/app/src/main/res/layout/activity_doc_view.xml67
-rw-r--r--platform/android/example/app/src/main/res/layout/activity_main.xml6
-rw-r--r--platform/android/example/app/src/main/res/layout/choose_doc.xml32
-rw-r--r--platform/android/example/app/src/main/res/layout/picker_entry.xml25
-rw-r--r--platform/android/example/app/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 3418 bytes
-rw-r--r--platform/android/example/app/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 2206 bytes
-rw-r--r--platform/android/example/app/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 4842 bytes
-rw-r--r--platform/android/example/app/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 7718 bytes
-rw-r--r--platform/android/example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin0 -> 10486 bytes
-rw-r--r--platform/android/example/app/src/main/res/values/colors.xml4
-rw-r--r--platform/android/example/app/src/main/res/values/strings.xml10
-rw-r--r--platform/android/example/app/src/main/res/values/styles.xml8
-rw-r--r--platform/android/example/build.gradle18
-rw-r--r--platform/android/example/local.properties.sample5
-rw-r--r--platform/android/example/mupdf/build.gradle52
-rw-r--r--platform/android/example/mupdf/proguard-rules.pro17
-rw-r--r--platform/android/example/mupdf/src/main/AndroidManifest.xml12
-rw-r--r--platform/android/example/mupdf/src/main/res/values/strings.xml3
-rw-r--r--platform/android/example/settings.gradle1
43 files changed, 827 insertions, 0 deletions
diff --git a/platform/android/example/README b/platform/android/example/README
new file mode 100644
index 00000000..9a2acc77
--- /dev/null
+++ b/platform/android/example/README
@@ -0,0 +1,12 @@
+This is a very basic example viewer using the new JNI classes.
+
+The build system is a bit incomplete.
+
+You need gradle 2.10 (exactly!).
+
+Copy the libmupdf_java.so file from the original viewer build:
+ $ cd ../viewer && ndk-build
+ $ cp ../viewer/libs/armeabi-v7a/libmupdf_java.so mupdf/libs/armeabi-v7a/libmupdf_java.so
+
+Build and install on device:
+ $ gradle-2.10 installArmDebug
diff --git a/platform/android/example/app/build.gradle b/platform/android/example/app/build.gradle
new file mode 100644
index 00000000..5d433deb
--- /dev/null
+++ b/platform/android/example/app/build.gradle
@@ -0,0 +1,46 @@
+apply plugin: 'com.android.model.application'
+
+model {
+
+ android {
+ compileSdkVersion = 23
+ buildToolsVersion = "23.0.2"
+
+ defaultConfig.with {
+ applicationId = "com.artifex.mupdf.example"
+ minSdkVersion.apiLevel = 8
+ targetSdkVersion.apiLevel = 16
+ versionCode = 1
+ versionName = "1.0"
+ }
+ }
+
+ android.buildTypes {
+ release {
+ minifyEnabled = false
+ proguardFiles.add(file('proguard-rules.pro'))
+ }
+ }
+
+ android.productFlavors {
+ create("arm") {
+ ndk.with {
+ // You can customize the NDK configurations for each
+ // productFlavors and buildTypes.
+ abiFilters.add("armeabi")
+ }
+
+ }
+ }
+
+ /* This is important, it will run lint checks but won't abort build */
+ android.lintOptions {
+ abortOnError false
+ }
+
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar','*.so'])
+ compile project(':mupdf')
+}
diff --git a/platform/android/example/app/proguard-rules.pro b/platform/android/example/app/proguard-rules.pro
new file mode 100644
index 00000000..68e56937
--- /dev/null
+++ b/platform/android/example/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Applications/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/platform/android/example/app/src/main/AndroidManifest.xml b/platform/android/example/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..c1dc4e52
--- /dev/null
+++ b/platform/android/example/app/src/main/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.artifex.mupdf.example">
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="16" />
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <supports-screens
+ android:anyDensity="true"
+ android:largeScreens="true"
+ android:normalScreens="true"
+ android:smallScreens="true" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppBaseTheme">
+
+ <activity android:name=".MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name=".ChooseDocActivity"
+ android:configChanges="orientation|keyboardHidden|screenSize"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".DocViewActivity">
+ </activity>
+ </application>
+
+</manifest>
diff --git a/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocActivity.java b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocActivity.java
new file mode 100644
index 00000000..3fcb3064
--- /dev/null
+++ b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocActivity.java
@@ -0,0 +1,228 @@
+package com.artifex.mupdf.example;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.FileObserver;
+import android.os.Handler;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class ChooseDocActivity
+ extends Activity
+{
+ private ListView mListView;
+ private ChooseDocAdapter adapter;
+ static private File mDirectory;
+ static private File mStartingDirectory;
+ private File mParent;
+ private File[] mDirs;
+ private File[] mFiles;
+ private Handler mHandler;
+ private Runnable mUpdateFiles;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.choose_doc);
+
+ mHandler = new Handler();
+
+ String storageState = Environment.getExternalStorageState();
+ if (!Environment.MEDIA_MOUNTED.equals(storageState) &&
+ !Environment.MEDIA_MOUNTED_READ_ONLY.equals(storageState))
+ {
+ showMessage(getResources().getString(R.string.no_media_warning),
+ getResources().getString(R.string.no_media_hint),
+ getResources().getString(R.string.dismiss));
+
+ return;
+ }
+
+ if (mDirectory == null) {
+ mDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+ mStartingDirectory = mDirectory; // remember where we started
+ }
+
+ // Create the list...
+ mListView = (ListView)findViewById(R.id.fileListView);
+ mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ onListItemClick(mListView, view, position, id);
+ }
+ });
+
+ // Create a list adapter...
+ adapter = new ChooseDocAdapter(getLayoutInflater());
+ mListView.setAdapter(adapter);
+
+ // ...that is updated dynamically when files are scanned
+ mUpdateFiles = new Runnable() {
+ public void run() {
+ Resources res = getResources();
+ String appName = res.getString(R.string.app_name);
+ String version = res.getString(R.string.version);
+ String title = res.getString(R.string.picker_title_App_Ver_Dir);
+ setTitle(String.format(title, appName, version, mDirectory));
+
+ mParent = mDirectory.getParentFile();
+
+ mDirs = mDirectory.listFiles(new FileFilter() {
+
+ public boolean accept(File file) {
+ return file.isDirectory();
+ }
+ });
+ if (mDirs == null)
+ mDirs = new File[0];
+
+ mFiles = mDirectory.listFiles(new FileFilter() {
+
+ public boolean accept(File file) {
+ if (file.isDirectory())
+ return false;
+
+ String fname = file.getName().toLowerCase();
+
+ if (fname.endsWith(".pdf"))
+ return true;
+ if (fname.endsWith(".xps"))
+ return true;
+ if (fname.endsWith(".cbz"))
+ return true;
+ if (fname.endsWith(".epub"))
+ return true;
+ if (fname.endsWith(".png"))
+ return true;
+ if (fname.endsWith(".jpe"))
+ return true;
+ if (fname.endsWith(".jpeg"))
+ return true;
+ if (fname.endsWith(".jpg"))
+ return true;
+ if (fname.endsWith(".jfif"))
+ return true;
+ if (fname.endsWith(".jfif-tbnl"))
+ return true;
+ if (fname.endsWith(".tif"))
+ return true;
+ if (fname.endsWith(".tiff"))
+ return true;
+
+ return false;
+ }
+ });
+ if (mFiles == null)
+ mFiles = new File[0];
+
+ Arrays.sort(mFiles, new Comparator<File>() {
+ public int compare(File arg0, File arg1) {
+ return arg0.getName().compareToIgnoreCase(arg1.getName());
+ }
+ });
+
+ Arrays.sort(mDirs, new Comparator<File>() {
+ public int compare(File arg0, File arg1) {
+ return arg0.getName().compareToIgnoreCase(arg1.getName());
+ }
+ });
+
+ adapter.clear();
+
+ // add a button for going up one level
+ if (mParent != null)
+ if (!mDirectory.getAbsolutePath().equals(mStartingDirectory.getAbsolutePath()))
+ adapter.add(new ChooseDocItem(ChooseDocItem.Type.PARENT, getString(R.string.parent_directory), mParent.getAbsolutePath()));
+
+ for (File f : mDirs)
+ adapter.add(new ChooseDocItem(ChooseDocItem.Type.DIR, f.getName(), f.getAbsolutePath()));
+ for (File f : mFiles)
+ adapter.add(new ChooseDocItem(ChooseDocItem.Type.DOC, f.getName(), f.getAbsolutePath()));
+ }
+ };
+
+ // Start initial file scan...
+ mHandler.post(mUpdateFiles);
+
+ // ...and observe the directory and scan files upon changes.
+ FileObserver observer = new FileObserver(mDirectory.getPath(), FileObserver.CREATE | FileObserver.DELETE) {
+ public void onEvent(int event, String path) {
+ mHandler.post(mUpdateFiles);
+ }
+ };
+ observer.startWatching();
+ }
+
+ private void onListItemClick(ListView l, View v, int position, long id)
+ {
+ ChooseDocItem item = (ChooseDocItem) v.getTag();
+ File f = new File(item.path);
+ if (item.type== ChooseDocItem.Type.PARENT || item.type== ChooseDocItem.Type.DIR)
+ {
+ mDirectory = f;
+ mHandler.post(mUpdateFiles);
+ return;
+ }
+
+ // start a viewing activity
+ Uri uri = Uri.parse(f.getAbsolutePath());
+ Intent intent;
+ intent = new Intent(this, DocViewActivity.class);
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setData(uri);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // do another file scan to pick up changes to files since we were away
+ mHandler.post(mUpdateFiles);
+ }
+
+ // this hides the activity
+ @Override
+ public void onBackPressed() {
+ moveTaskToBack (true);
+ }
+
+ private void showMessage(final String title, final String body, final String okLabel)
+ {
+ final Activity activity = this;
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ new AlertDialog.Builder(activity)
+ .setTitle(title)
+ .setMessage(body)
+ .setCancelable(false)
+ .setPositiveButton(okLabel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ }).create().show();
+ }
+ });
+ }
+}
diff --git a/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocAdapter.java b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocAdapter.java
new file mode 100644
index 00000000..4b889a06
--- /dev/null
+++ b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocAdapter.java
@@ -0,0 +1,76 @@
+package com.artifex.mupdf.example;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.LinkedList;
+
+public class ChooseDocAdapter extends BaseAdapter {
+ private final LinkedList<ChooseDocItem> mItems;
+ private final LayoutInflater mInflater;
+
+ public ChooseDocAdapter(LayoutInflater inflater) {
+ mInflater = inflater;
+ mItems = new LinkedList<ChooseDocItem>();
+ }
+
+ public void clear() {
+ mItems.clear();
+ }
+
+ public void add(ChooseDocItem item) {
+ mItems.add(item);
+ notifyDataSetChanged();
+ }
+
+ public int getCount() {
+ return mItems.size();
+ }
+
+ public Object getItem(int i) {
+ return null;
+ }
+
+ public long getItemId(int arg0) {
+ return 0;
+ }
+
+ private int iconForType(ChooseDocItem.Type type, String docName)
+ {
+ switch (type)
+ {
+ case PARENT:
+ return R.drawable.ic_explorer_up;
+
+ case DIR:
+ return R.drawable.ic_explorer_fldr;
+
+ case DOC:
+ return R.drawable.ic_explorer_any;
+
+ default:
+ return 0;
+ }
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View v;
+ if (convertView == null) {
+ v = mInflater.inflate(R.layout.picker_entry, null);
+ } else {
+ v = convertView;
+ }
+ ChooseDocItem item = mItems.get(position);
+ ((TextView)v.findViewById(R.id.name)).setText(item.name);
+ ((ImageView)v.findViewById(R.id.icon)).setImageResource(iconForType(item.type, item.name));
+
+ v.setTag(item);
+
+ return v;
+ }
+
+}
diff --git a/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocItem.java b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocItem.java
new file mode 100644
index 00000000..194db0f3
--- /dev/null
+++ b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/ChooseDocItem.java
@@ -0,0 +1,17 @@
+package com.artifex.mupdf.example;
+
+public class ChooseDocItem {
+ public enum Type {
+ PARENT, DIR, DOC
+ }
+
+ final public Type type;
+ final public String name;
+ final public String path;
+
+ public ChooseDocItem(Type t, String n, String p) {
+ type = t;
+ name = n;
+ path = p;
+ }
+}
diff --git a/platform/android/example/app/src/main/java/com/artifex/mupdf/example/DocViewActivity.java b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/DocViewActivity.java
new file mode 100644
index 00000000..a0e989ff
--- /dev/null
+++ b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/DocViewActivity.java
@@ -0,0 +1,105 @@
+package com.artifex.mupdf.example;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.artifex.mupdf.fitz.ColorSpace;
+import com.artifex.mupdf.fitz.Document;
+import com.artifex.mupdf.fitz.Matrix;
+import com.artifex.mupdf.fitz.Page;
+import com.artifex.mupdf.fitz.Pixmap;
+
+public class DocViewActivity extends Activity
+{
+ private int mPageCount;
+ private int mCurrentPage;
+
+ Document mDocument;
+ Page mPage;
+ Bitmap mBitmap = null;
+
+ ImageView mImageView;
+ TextView mTextView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_doc_view);
+
+ mImageView = (ImageView)findViewById(R.id.image_view);
+ mTextView = (TextView)findViewById(R.id.page_text);
+
+ // load the doc
+ Uri uri = getIntent().getData();
+ String path = Uri.decode(uri.getEncodedPath());
+ mDocument = new Document(path);
+ mPageCount = mDocument.countPages();
+
+ // show the first page
+ mCurrentPage = 0;
+ displayCurrentPage();
+ }
+
+ public void onFirstPageButton(final View v)
+ {
+ mCurrentPage = 0;
+ displayCurrentPage();
+ }
+
+ public void onPreviousPageButton(final View v)
+ {
+ if (mCurrentPage > 0)
+ {
+ mCurrentPage--;
+ displayCurrentPage();
+ }
+ }
+
+ public void onNextPageButton(final View v)
+ {
+ if (mCurrentPage < mPageCount-1)
+ {
+ mCurrentPage++;
+ displayCurrentPage();
+ }
+ }
+
+ public void onLastPageButton(final View v)
+ {
+ mCurrentPage = mPageCount-1;
+ displayCurrentPage();
+ }
+
+ private void displayCurrentPage()
+ {
+ // report the page number
+ mTextView.setText(String.format("page %d of %d",mCurrentPage+1,mPageCount));
+
+ // get the page
+ mPage = mDocument.loadPage(mCurrentPage);
+
+ // create a matrix that renders at 300 DPI
+ Matrix m = new Matrix();
+ m.scale(300.0f/72.0f);
+
+ // create a new bitmap for the page
+ Bitmap old = mBitmap;
+ Pixmap pixmap = mPage.toPixmap(m, ColorSpace.DeviceBGR);
+ mBitmap = Bitmap.createBitmap(pixmap.getWidth(), pixmap.getHeight(), Bitmap.Config.ARGB_8888);
+ int [] pixels = pixmap.getPixels();
+ mBitmap.setPixels(pixels, 0, pixmap.getWidth(), 0, 0, pixmap.getWidth(), pixmap.getHeight());
+
+ // set the bitmap in the UI
+ mImageView.setImageBitmap(mBitmap);
+
+ // recycle the old bitmap
+ if (old!=null)
+ old.recycle();
+ }
+}
diff --git a/platform/android/example/app/src/main/java/com/artifex/mupdf/example/MainActivity.java b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/MainActivity.java
new file mode 100644
index 00000000..b7aa39ca
--- /dev/null
+++ b/platform/android/example/app/src/main/java/com/artifex/mupdf/example/MainActivity.java
@@ -0,0 +1,20 @@
+package com.artifex.mupdf.example;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class MainActivity extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // just show the document chooser activity
+ Intent intent = new Intent(this, ChooseDocActivity.class);
+ startActivity(intent);
+ finish();
+ }
+
+}
diff --git a/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_any.png b/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_any.png
new file mode 100755
index 00000000..1ec7c5f3
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_any.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_fldr.png b/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_fldr.png
new file mode 100755
index 00000000..8156137e
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_fldr.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_up.png b/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_up.png
new file mode 100755
index 00000000..7adeab26
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-hdpi/ic_explorer_up.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_any.png b/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_any.png
new file mode 100755
index 00000000..ee4ed481
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_any.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_fldr.png b/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_fldr.png
new file mode 100755
index 00000000..6a1c9862
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_fldr.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_up.png b/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_up.png
new file mode 100755
index 00000000..48b7ea04
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-mdpi/ic_explorer_up.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_any.png b/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_any.png
new file mode 100755
index 00000000..50e224a4
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_any.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_fldr.png b/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_fldr.png
new file mode 100755
index 00000000..0df4d0c4
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_fldr.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_up.png b/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_up.png
new file mode 100755
index 00000000..f089e8d7
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xhdpi/ic_explorer_up.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_any.png b/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_any.png
new file mode 100755
index 00000000..9aea910c
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_any.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_fldr.png b/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_fldr.png
new file mode 100755
index 00000000..f0eefc36
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_fldr.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_up.png b/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_up.png
new file mode 100755
index 00000000..af79349e
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xxhdpi/ic_explorer_up.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_any.png b/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_any.png
new file mode 100755
index 00000000..6a653115
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_any.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_fldr.png b/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_fldr.png
new file mode 100755
index 00000000..e06c1b25
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_fldr.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_up.png b/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_up.png
new file mode 100755
index 00000000..243c3c65
--- /dev/null
+++ b/platform/android/example/app/src/main/res/drawable-xxxhdpi/ic_explorer_up.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/layout/activity_doc_view.xml b/platform/android/example/app/src/main/res/layout/activity_doc_view.xml
new file mode 100644
index 00000000..05cee21a
--- /dev/null
+++ b/platform/android/example/app/src/main/res/layout/activity_doc_view.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="|&lt;-"
+ android:id="@+id/first_page_button"
+ android:onClick="onFirstPageButton"
+ android:minWidth="60dp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="&lt;"
+ android:id="@+id/previous_page_button"
+ android:onClick="onPreviousPageButton"
+ android:minWidth="60dp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text=">"
+ android:id="@+id/next_page_button"
+ android:onClick="onNextPageButton"
+ android:minWidth="60dp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="->|"
+ android:id="@+id/last_page_button"
+ android:onClick="onLastPageButton"
+ android:minWidth="60dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="Medium Text"
+ android:textColor="@color/white"
+ android:id="@+id/page_text" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:id="@+id/image_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ </ImageView>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/platform/android/example/app/src/main/res/layout/activity_main.xml b/platform/android/example/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..24f3d6ba
--- /dev/null
+++ b/platform/android/example/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/example/app/src/main/res/layout/choose_doc.xml b/platform/android/example/app/src/main/res/layout/choose_doc.xml
new file mode 100644
index 00000000..48e63b8c
--- /dev/null
+++ b/platform/android/example/app/src/main/res/layout/choose_doc.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/device_files_wrapper">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/file_list_wrpper">
+
+ <ListView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/fileListView"
+ android:layout_gravity="center_horizontal"
+ android:choiceMode="singleChoice"
+ android:background="#ffffff"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/platform/android/example/app/src/main/res/layout/picker_entry.xml b/platform/android/example/app/src/main/res/layout/picker_entry.xml
new file mode 100644
index 00000000..98ede7d6
--- /dev/null
+++ b/platform/android/example/app/src/main/res/layout/picker_entry.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="4dp" >
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentLeft="true" />
+
+ <TextView
+ android:id="@+id/name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/icon"
+ android:paddingBottom="4dp"
+ android:paddingLeft="10dp"
+ android:paddingRight="4dp"
+ android:paddingTop="4dp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</RelativeLayout>
diff --git a/platform/android/example/app/src/main/res/mipmap-hdpi/ic_launcher.png b/platform/android/example/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..cde69bcc
--- /dev/null
+++ b/platform/android/example/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/mipmap-mdpi/ic_launcher.png b/platform/android/example/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..c133a0cb
--- /dev/null
+++ b/platform/android/example/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/platform/android/example/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..bfa42f0e
--- /dev/null
+++ b/platform/android/example/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/platform/android/example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..324e72cd
--- /dev/null
+++ b/platform/android/example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/platform/android/example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..aee44e13
--- /dev/null
+++ b/platform/android/example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/platform/android/example/app/src/main/res/values/colors.xml b/platform/android/example/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..b8acf28a
--- /dev/null
+++ b/platform/android/example/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="white">#FFFFFFFF</color>
+</resources>
diff --git a/platform/android/example/app/src/main/res/values/strings.xml b/platform/android/example/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..3d985824
--- /dev/null
+++ b/platform/android/example/app/src/main/res/values/strings.xml
@@ -0,0 +1,10 @@
+<resources>
+ <string name="app_name">MuPDF Example</string>
+ <string name="ok">OK</string>
+ <string name="version">1.0</string>
+ <string name="no_media_warning">Storage media not present</string>
+ <string name="no_media_hint">Sharing the storage media with a PC can make it inaccessible</string>
+ <string name="dismiss">Dismiss</string>
+ <string name="picker_title_App_Ver_Dir">%1$s %2$s: %3$s</string>
+ <string name="parent_directory">[Up one level]</string>
+</resources>
diff --git a/platform/android/example/app/src/main/res/values/styles.xml b/platform/android/example/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..3d804574
--- /dev/null
+++ b/platform/android/example/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppBaseTheme" parent="@android:style/Theme.NoTitleBar.Fullscreen">
+ </style>
+
+</resources> \ No newline at end of file
diff --git a/platform/android/example/build.gradle b/platform/android/example/build.gradle
new file mode 100644
index 00000000..d92ef895
--- /dev/null
+++ b/platform/android/example/build.gradle
@@ -0,0 +1,18 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha9'
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
diff --git a/platform/android/example/local.properties.sample b/platform/android/example/local.properties.sample
new file mode 100644
index 00000000..bc40e6ef
--- /dev/null
+++ b/platform/android/example/local.properties.sample
@@ -0,0 +1,5 @@
+# Uncomment and edit the appropriate line below.
+# Resave this file as local.properties.
+
+sdk.dir=/path/to/android/sdk
+ndk.dir=/path/to/android/ndk
diff --git a/platform/android/example/mupdf/build.gradle b/platform/android/example/mupdf/build.gradle
new file mode 100644
index 00000000..0add44db
--- /dev/null
+++ b/platform/android/example/mupdf/build.gradle
@@ -0,0 +1,52 @@
+apply plugin: 'com.android.model.library'
+
+model {
+
+ android {
+ compileSdkVersion = 23
+ buildToolsVersion = "23.0.2"
+ }
+
+ android.buildTypes {
+ release {
+ minifyEnabled = false
+ proguardFiles.add(file('proguard-rules.pro'))
+ }
+ }
+
+ android.sources {
+ main {
+ java {
+ source {
+ srcDir '../../../java'
+ exclude 'example'
+ }
+ }
+ jniLibs {
+ dependencies {
+ library "libmupdf_java"
+ }
+ }
+ }
+ }
+
+ repositories {
+ prebuilt(PrebuiltLibraries) {
+ libmupdf_java {
+ binaries.withType(SharedLibraryBinary) {
+ sharedLibraryFile = file("libs/armeabi-v7a/libmupdf_java.so")
+ }
+ }
+ }
+ }
+
+ /* This is important, it will run lint checks but won't abort build */
+ android.lintOptions {
+ abortOnError false
+ }
+
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar','*.so'])
+}
diff --git a/platform/android/example/mupdf/proguard-rules.pro b/platform/android/example/mupdf/proguard-rules.pro
new file mode 100644
index 00000000..68e56937
--- /dev/null
+++ b/platform/android/example/mupdf/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Applications/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/platform/android/example/mupdf/src/main/AndroidManifest.xml b/platform/android/example/mupdf/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..ee014902
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.artifex.mupdf.fitz">
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/>
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:supportsRtl="true">
+ </application>
+</manifest>
diff --git a/platform/android/example/mupdf/src/main/res/values/strings.xml b/platform/android/example/mupdf/src/main/res/values/strings.xml
new file mode 100644
index 00000000..0fba1bfb
--- /dev/null
+++ b/platform/android/example/mupdf/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">MuPDF</string>
+</resources>
diff --git a/platform/android/example/settings.gradle b/platform/android/example/settings.gradle
new file mode 100644
index 00000000..c70199dd
--- /dev/null
+++ b/platform/android/example/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':mupdf'