一、基本实现
1,导入so库;
2,声明库文件中方法
public class MuPDFCore { /* load our native library */ static { System.loadLibrary("mupdf"); } /* Readable members */ private int pageNum = -1;; private int numPages = -1; public float pageWidth; public float pageHeight; /* The native functions */ private static native int openFile(String filename); private static native int countPagesInternal(); private static native void gotoPageInternal(int localActionPageNum); private static native float getPageWidth(); private static native float getPageHeight(); public static native void drawPage(Bitmap bitmap, int pageW, int pageH, int patchX, int patchY, int patchW, int patchH); public static native RectF[] searchPage(String text); public static native int getPageLink(int page, float x, float y); public static native boolean hasOutlineInternal(); public static native boolean needsPasswordInternal(); public static native boolean authenticatePasswordInternal(String password); public static native void destroying(); public MuPDFCore(String filename) throws Exception { if (openFile(filename) <= 0) { throw new Exception("Failed to open " + filename); } } public int countPages() { if (numPages < 0) numPages = countPagesSynchronized(); return numPages; } private synchronized int countPagesSynchronized() { return countPagesInternal(); } /* Shim function */ public void gotoPage(int page) { if (page > numPages - 1) page = numPages - 1; else if (page < 0) page = 0; if (this.pageNum == page) return; gotoPageInternal(page); this.pageNum = page; this.pageWidth = getPageWidth(); this.pageHeight = getPageHeight(); } public synchronized PointF getPageSize(int page) { gotoPage(page); return new PointF(pageWidth, pageHeight); } public synchronized void onDestroy() { destroying(); } public synchronized void drawPage(int page, Bitmap bitmap, int pageW,int pageH, int patchX, int patchY, int patchW, int patchH) { gotoPage(page); drawPage(bitmap, pageW, pageH, patchX, patchY, patchW, patchH); } public synchronized int hitLinkPage(int page, float x, float y) { return getPageLink(page, x, y); } public synchronized RectF[] searchPage(int page, String text) { gotoPage(page); return searchPage(text); } public synchronized boolean hasOutline() { return hasOutlineInternal(); } public synchronized boolean needsPassword() { return needsPasswordInternal(); } public synchronized boolean authenticatePassword(String password) { return authenticatePasswordInternal(password); } }
public class MuPDFActivity extends BaseActivity {
private MuPDFCore core;
private String mFileName;
private ListView mDocListView;
private View mButtonsView;
private boolean mButtonsVisible;
private EditText mPasswordView;
private TextView mFilenameView;
private SeekBar mPageSlider;
private TextView mPageNumberView;
private ViewSwitcher mTopBarSwitcher;
private ProgressBar loadingPB;
private MyMuPDFPageAdapter pdfPageAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (core == null) {
File sdcardDir = Environment.getExternalStorageDirectory();
// 得到一个路径,内容是sdcard的文件夹路径和名字
String path = sdcardDir.getPath() + "/MyMobileDownlod/test.pdf";
int lastSlashPos = path.lastIndexOf('/');
mFileName = new String(lastSlashPos == -1 ? path
: path.substring(lastSlashPos + 1));
System.out.println("Trying to open " + path);
try {
core = new MuPDFCore(path);
} catch (Exception e) {
}
if (core != null && core.needsPassword()) {
return;
}
}
if (core == null) {
AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setTitle(R.string.open_failed);
alert.setButton(AlertDialog.BUTTON_POSITIVE, "Dismiss",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
return;
}
createUI(savedInstanceState);
}
public void createUI(Bundle savedInstanceState) {
mDocListView = new ListView(this);
pdfPageAdapter = new MyMuPDFPageAdapter(this, core);
mDocListView.setAdapter(pdfPageAdapter);
mButtonsView = getLayoutInflater().inflate(R.layout.buttons, null);
mFilenameView = (TextView) mButtonsView.findViewById(R.id.docNameText);
loadingPB = (ProgressBar) mButtonsView.findViewById(R.id.loadingPB);
mTopBarSwitcher = (ViewSwitcher) mButtonsView
.findViewById(R.id.switcher);
mTopBarSwitcher.setDisplayedChild(0);
mTopBarSwitcher.setVisibility(View.VISIBLE);
loadingPB.setVisibility(View.INVISIBLE);
mFilenameView.setText("Name:" + mFileName
+ String.format(" SumPage:%d", core.countPages()));
RelativeLayout layout = new RelativeLayout(this);
layout.addView(mDocListView);
layout.addView(mButtonsView);
layout.setBackgroundResource(R.drawable.tiled_background);
setContentView(layout);
}
public void onDestroy() {
if (core != null)
core.onDestroy();
core = null;
super.onDestroy();
}
@Override
protected void dispatchMsgOP(Message msg) {
super.dispatchMsgOP(msg);
if (1 == msg.what) {
Toast.makeText(MuPDFActivity.this, "loading", Toast.LENGTH_SHORT)
.show();
loadingPB.setVisibility(View.VISIBLE);
} else {
loadingPB.setVisibility(View.INVISIBLE);
}
}
}
4,展示效果【实际应用】
实际使用说明:
当前PDF阅读器的实质是一个ListView,从而可以实现当前页面的重新布局,以达到实际需求。如:title栏变更效果,增加“分享”等后续操作。
二、so库的使用
1,导入so库源文件
so库分包有armeabi,arm64-v8a,armeabi-v7a等,是针对不同的ARM设备的包。armeabi,armeabi-v7a是32位ARM设备,arm64-v8a是64位ARM设备。arm64-v8a是向下兼容的,每个包有自己的优化和处理,最理想的条件是每个设备类型都有对应的so库文件。
注意事项是arm64-v8a中一定要有全部的armeabi的源文件,否则在调用到armeabi中独有的就会出错。当存在arm64-v8a中没有armeabi的so库文件时,只能删除整个包,保证程序能够正常运行。
2,关联库文件
static {
System.loadLibrary("mupdf");//加载库文件
}
生命so库文件中存在的方法,从而能够正常使用。后续调用,只是类本身之间的调用,遵循类的规则即可。
三、使用细节注意
1,包名一致【JNI调用规则】
Java_ + 包名(com.lucyfyr) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;
so库文件中方法在使用时,必须保证使用环境的包名与so库文件编译生成的包名一致。
2,so库的注意事项
注意事项:arm64-v8a中一定要有全部的armeabi的源文件,否则在调用到armeabi中独有文件方法时就会出错。当存在arm64-v8a中没有armeabi的so库文件时,只能删除整个包,保证程序能够正常运行。或者重新编译生成so库文件。
这里是源码