0

Ich entwerfe ein benutzerdefiniertes Plugin für Cordova als pädagogische Demonstration. Das Plugin integriert sich in die Android PdfRenderer-Klasse und stellt die API dem Cordova-Ökosystem zur Verfügung.Cordova Android Benutzerdefinierte Plugin/App - Klasse nicht gefunden Ausnahme für benutzerdefinierte Plugin

Mein benutzerdefiniertes Plugin kompiliert ohne Fehler, und ich habe das Plugin zu meinem Testprojekt hinzugefügt. Als ich das Testprojekt erstellen und ausführen, aber ich stürzt die Anwendung beim Start und ich mit der folgenden Meldung erfüllt:

java.lang.ClassNotFoundException: com.dev.plugin.PdfRendererPlugin

Ich habe meine platforms/android/ Ordner überprüft und die Plugin-Klasse gefunden bei src/com/dev/plugin/PdfRenderPlugin.java wie erwartet.

Worauf sollte ich in dieser Situation noch achten? Es scheint, dass meine Anwendung jetzt gut funktionieren sollte, wenn das Plugin kompiliert und ohne Fehler zum Projekt hinzugefügt wird.

Hier ist ein Code, mit zu arbeiten:

plugin.xml

<?xml version="1.0" encoding="UTF-8"?> 
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" 
    id="cordova-android-pdf-renderer-plugin" version="0.2.3"> 
<name>PdfRendererPlugin</name> 
<description>Cordova PDF Renderer Plugin</description> 
<license>MIT</license> 
<keywords>cordova,pdf,renderer</keywords> 

<platform name="android"> 
    <js-module src="www/js/PdfRendererPlugin.js" name="PdfRendererPlugin"> 
     <runs/> 

     <clobbers target="PdfRendererPlugin" /> 
    </js-module> 

    <config-file target="config.xml" parent="/*"> 
     <feature name="com.dev.plugin.PdfRendererPlugin"> 
      <param name="android-package" value="com.dev.plugin.PdfRendererPlugin"/> 
      <param name="onload" value="true" /> 
     </feature> 
    </config-file> 

    <source-file src="src/android/PdfRendererPlugin.java" target-dir="src/com/dev/plugin/" /> 
</platform> 
</plugin> 

Plugin-Klasse (PdfRendererService)

package com.dev.plugin.PdfRendererService; 

import org.apache.cordova.CordovaInterface; 
import org.apache.cordova.CordovaPlugin; 
import org.apache.cordova.CordovaWebView; 
import org.apache.cordova.CallbackContext; 
import org.apache.cordova.PluginResult; 

import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 

import android.content.pm.PackageManager; 

import android.graphics.Bitmap; 
import android.graphics.pdf.PdfRenderer; 
import android.graphics.pdf.PdfRenderer.Page; 

import android.os.ParcelFileDescriptor; 

import android.util.Log; 

/** 
* This class handles a pdf file called from JavaScript and converts a selected 
page (default is first) to a byte array representing a bitmap. 
*/ 
public class PdfRendererPlugin extends CordovaPlugin { 

private static final String LOG_TAG = "PdfRendererPlugin"; 

private ParcelFileDescriptor fileDescriptor = null; 
private PdfRenderer renderer = null; 
private Page currentPage = null; 

private int mWidth = 400, mHeight = 600; 
private String mRenderMode = "display"; 

@Override 
public void initialize(CordovaInterface cordova, CordovaWebView webView){ 
    Log.d(LOG_TAG, "initialize"); 
    super.initialize(cordova, webView); 
} 

@Override 
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { 
    Log.d(LOG_TAG, "execute"); 

    //No Switch -> src 1.6 
    if(action.equals("open")){ 
     return executeOpen(args, callbackContext); 
    } 
    else if(action.equals("renderPage")){ 
     return executeRenderPage(args, callbackContext); 
    } 
    else if(action.equals("pageCount")){ 
     callbackContext.success(this.getPageCount()); 
     return true; 
    } 
    else if(action.equals("close")){ 
     this.closeRenderer(); 
     callbackContext.success(); 
     return true; 
    } 

    return false; 
} 

private boolean executeOpen(JSONArray args, CallbackContext callbackContext){ 
    Log.d(LOG_TAG, "executeOpen"); 
    String filePath = ""; 
    try{ 
     if(args.length() < 1){ 
      Log.e(LOG_TAG, "No arguments provided. Exiting process."); 
      callbackContext.error("No arguments provided. Exiting process."); 
      return true; 
     } 
     else if(args.length() < 2){ 
      Log.e(LOG_TAG, "Insufficient arguments provided. Exiting process."); 
      callbackContext.error("Insufficient arguments provided. Exiting process."); 
      return true; 
     } 
     if(args.length() > 3){ 
      mWidth = args.getInt(2); 
      mHeight = args.getInt(3); 
     } 

     filePath = args.getString(0); 
     mRenderMode = args.getString(1); 
    } 
    catch(JSONException je){ 
     String msg = je.getMessage(); 
     if(msg == null) 
      msg = "Unknown JSONException has occurred"; 
     Log.e(LOG_TAG, msg); 
    } 

    this.initializeRenderer(filePath, callbackContext); 

    boolean isPageOpen = this.openPage(0, callbackContext); 
    if(isPageOpen){ 
     Bitmap bitmap = getBitmap(mWidth, mHeight); 
     this.sendBitmapAsBytes(0, bitmap, callbackContext); 
    } 
    return true; 
} 

private boolean executeRenderPage(JSONArray args, CallbackContext callbackContext){ 
    Log.d(LOG_TAG, "executeRenderPage"); 
    int pageNo = -1; 
    try { 
     if (args.length() < 1) { 
      Log.e(LOG_TAG, "No arguments provided. Exiting process."); 
      callbackContext.error("No arguments provided. Exiting process."); 
      return true; 
     } 
     if (args.length() > 1) { 
      mRenderMode = args.getString(1); 
     } 
     if (args.length() > 3) { 
      mWidth = args.getInt(2); 
      mHeight = args.getInt(3); 
     } 

     pageNo = args.getInt(0); 
    } 
    catch(JSONException je){ 
     String msg = je.getMessage(); 
     if(msg == null) 
      msg = "Unknown JSONException has occurred"; 
     Log.e(LOG_TAG, msg); 
    } 

    if(pageNo < 0) 
     return false; 

    boolean isPageOpen = this.openPage(pageNo, callbackContext); 
    if(isPageOpen) { 
     Bitmap bitmap = getBitmap(mWidth, mHeight); 
     this.sendBitmapAsBytes(pageNo, bitmap, callbackContext); 
    } 
    return true; 
} 

/* 
// Requests the permission to read from external storage if not already available 
private void validatePermissions(){ 
    Log.d(LOG_TAG, "validatePermissions"); 
    if(!cordova.hasPermission(READ_EXTERNAL_STORAGE)){ 
     Log.i(LOG_TAG, "Requesting External Storage Read Permission..."); 
     cordova.requestPermission(this, CODE_READ_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE); 
    } 
} 
*/ 

private int getPageCount() { 
    Log.d(LOG_TAG, "getPageCount"); 
    if(renderer == null) 
     return 0; 

    return renderer.getPageCount(); 
} 

private void initializeWriteFileDescriptor(String filePath, CallbackContext callbackContext) throws FileNotFoundException, FileFormatException { 
    Log.d(LOG_TAG, "initializeWriteFileDescriptor"); 
    fileDescriptor = null; 

    if(filePath == null || filePath.length() < 1) 
     throw new FileNotFoundException("The file path provided is not a valid file path."); 

    String[] pathArr = filePath.split("."); 
    int numSections = pathArr.length; 
    String ext = pathArr[numSections - 1]; 

    if(!ext.equals("pdf")) 
     throw new FileFormatException("Invalid File Extension provided to Pdf Render Service: " + ext); 

    fileDescriptor = getWriteFileDescriptor(filePath); 
} 

private void initializeRenderer(String filePath, CallbackContext callbackContext){ 
    Log.d(LOG_TAG, "initializeRenderer"); 
    renderer = null; 

    try { 
     initializeWriteFileDescriptor(filePath, callbackContext); 

     renderer = new PdfRenderer(fileDescriptor); 
    } 
    catch(IOException io){ 
     String msg = io.getMessage(); 
     if(msg == null) 
      msg = "An error has occurred while loading the requested file."; 

     Log.e(LOG_TAG, msg); 
     callbackContext.error(msg); 
    } 
} 

private void closeRenderer() { 
    Log.d(LOG_TAG, "closeRenderer"); 
    if(renderer == null) { 
     Log.w(LOG_TAG, "Attempted to close null renderer. Skipping operation."); 
     return; 
    } 

    renderer.close(); 
} 

private boolean openPage(int index, CallbackContext callbackContext){ 
    Log.d(LOG_TAG, "openPage"); 
    currentPage = null; 

    int pageCount = getPageCount(); 
    if(pageCount < 1) { 
     Log.e(LOG_TAG, "Requested document has no pages to display."); 
     callbackContext.error("Requested document has no pages to display."); 
     return false; 
    } 

    if(index >= pageCount || index < 0) { 
     Log.e(LOG_TAG, String.format("No page was found at page number %d/%d", index, pageCount)); 
     callbackContext.error(String.format("No page was found at page number %d/%d", index, pageCount)); 
     return false; 
    } 

    currentPage = renderer.openPage(index); 
    return true; 
} 

private void sendBitmapAsBytes(int index, Bitmap bitmap, CallbackContext callbackContext){ 
    Log.d(LOG_TAG, "sendBitmapAsBytes"); 
    if(renderer == null) { 
     Log.e(LOG_TAG, "Renderer was not properly initialized."); 
     callbackContext.error("Renderer was not properly initialized."); 
     return; 
    } 

    if(currentPage == null) { 
     Log.e(LOG_TAG, "Requested page could not be rendered."); 
     callbackContext.error("Requested page could not be rendered."); 
     return; 
    } 

    int renderMode = mRenderMode.equals("print") ? Page.RENDER_MODE_FOR_PRINT : Page.RENDER_MODE_FOR_DISPLAY; 
    currentPage.render(bitmap, null, null, renderMode); 

    byte[] output = toByteArray(bitmap); 
    if(output == null || output.length < 1) { 
     Log.e(LOG_TAG, "Bitmap Error has occurred: Invalid Output Format Detected"); 
     callbackContext.error("Bitmap Error has occurred: Invalid Output Format Detected"); 
    } 
    else { 
     Log.i(LOG_TAG, "Bitmap Conversion Successful"); 
     callbackContext.success(output); 
    } 
} 

private static byte[] toByteArray(Bitmap bitmap){ 
    Log.d(LOG_TAG, "toByteArray"); 
    ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); 

    return stream.toByteArray(); 
} 

private static Bitmap getBitmap(int width, int height){ 
    Log.d(LOG_TAG, "getBitmap"); 
    return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
} 

private static ParcelFileDescriptor getWriteFileDescriptor(String filePath) throws FileNotFoundException { 
    Log.d(LOG_TAG, "getWriteFileDescriptor"); 
    File file = new File(filePath); 
    final int fileMode = ParcelFileDescriptor.MODE_TRUNCATE | 
         ParcelFileDescriptor.MODE_CREATE | 
         ParcelFileDescriptor.MODE_WRITE_ONLY; 

    return ParcelFileDescriptor.open(file, fileMode); 
} 

class FileFormatException extends IOException { 
    FileFormatException(String msg){ 
     super(msg); 
    } 
} 
} 

Plugin JS Schnittstelle

var PLUGIN_NAME = "PdfRendererPlugin"; 

var SERVICE_OPEN = "open"; 
var SERVICE_CLOSE = "close"; 
var SERVICE_PAGE_COUNT = "pageCount"; 
var SERVICE_RENDER_PAGE = "renderPage"; 

var RENDER_MODE_DISPLAY = "display"; 
var RENDER_MODE_PRINT = "print"; 

var PdfRendererPlugin = { 
display: function(filePath, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_OPEN, [filePath, RENDER_MODE_DISPLAY]); 
}, 

displayWithDimensions: function(filePath, width, height, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_OPEN, [filePath, RENDER_MODE_DISPLAY, width, height]); 
}, 

print: function(filePath, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_OPEN, [filePath, RENDER_MODE_PRINT]); 
}, 

printWithDimensions: function(filePath, width, height, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_OPEN, [filePath, RENDER_MODE_PRINT, width, height]); 
}, 

renderPage: function(pageNo, callback){ 
    cordova.exec(callback, function(err){ 
     //console.log(err); 
    }, PLUGIN_NAME, SERVICE_RENDER_PAGE, [pageNo]); 
}, 

renderPageForDisplay: function(pageNo, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_RENDER_PAGE, [pageNo, RENDER_MODE_DISPLAY]); 
}, 

renderPageForDisplayWithDimensions: function(pageNo, width, height, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_RENDER_PAGE, [pageNo, RENDER_MODE_DISPLAY, width, height]); 
}, 

renderPageForPrint: function(pageNo, callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_RENDER_PAGE, [pageNo, RENDER_MODE_PRINT]); 
}, 

renderPageForPrintWithDimensions: function(pageNo, width, height, callback){ 
    cordova.exec(callback, function(err){ 
     //console.log(err); 
    }, PLUGIN_NAME, SERVICE_RENDER_PAGE, [pageNo, RENDER_MODE_PRINT, width, height]); 
}, 

close: function(callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_CLOSE, []); 
}, 

getPageCount: function(callback){ 
    cordova.exec(callback, function(err){ 
     // console.log(err); 
    }, PLUGIN_NAME, SERVICE_PAGE_COUNT, []); 
} 
}; 

-Test Applicat Ion index.html

<!DOCTYPE html> 
<html> 
<head> 
    <title>Cordova PDF Generator Plugin Test</title> 

    <meta name="viewport" content="user-scalable=no, initial-scale=1, 
      maximum-scale=1, minimum-scale=1, width=device-width, 
      height=device-height" /> 
</head> 
<body> 
    <div class="app"> 
     <h1>Cordova PDF Generation Plugin Test</h1> 

     <div> 
      <button id="display-button" onclick="display()">Display (View)</button> 
      <button id="print-button" onclick="print()">Display (Print)</button> 
     </div> 
    </div> 

    <script type="text/javascript" src="cordova.js"></script> 
    <script type="text/javascript" src="js/index.js"></script> 
</body> 
</html> 

Test Application index.js

var testFilePath = 'assets/test-file.pdf'; 

var app = { 
// Application Constructor 
initialize: function() { 
    document.addEventListener('deviceready', this.onDeviceReady.bind(this), false); 
}, 

// deviceready Event Handler 
// 
// Bind any cordova events here. Common events are: 
// 'pause', 'resume', etc. 
onDeviceReady: function() { 
    display(); 
} 
}; 

var display = function(){ 
PdfRendererPlugin.display(testFilePath, function(data){ 
     console.log('Bitmap Bytes'); 
     console.log(data); 
    }); 
}; 

var print = function(){ 
PdfRendererPlugin.print(testFilePath, function(data){ 
     console.log('Bitmap Bytes'); 
     console.log(data); 
    }); 
}; 

app.initialize(); 

Antwort

0

Ich fühle mich dumm. Das Problem war mit der Paketdeklaration. Ich habe der Paketdeklaration den Klassennamen hinzugefügt, ohne darüber nachzudenken (es muss daran liegen, dass ich den Pfad aus der Datei plugin.xml, die den Klassennamen enthält, kopiert und eingefügt habe).

Verwandte Themen