草庐IT

android - 如何在 android 中使用 jquery 和 phonegap 打开 pdf 文件?

coder 2023-11-27 原文

最近我正在为 android 构建一个应用程序。我正在使用 phonegap 做同样的事情。一切都运行良好,除了一个问题,即我无法在 android 中使用 jquery 打开 pdf 文件。我已经尝试了很多来做同样的事情,但我做不到。

我想要的是点击图片后它会从 url 打开 pdf。

已编辑:

我试过这个:

<img src="img/b_img1.png" onclick="openPdf('http://www.w3.org/2011/web-apps-ws/papers/Nitobi.pdf')"/>

openPdf 函数是这样的:

 function openFile(pdfUrl) {
     window.plugins.fileOpener.open(pdfUrl);
 }

fileOpener 插件就是这样的:

cordova.define("cordova/plugin/fileopener",
    function(require, exports, module) {
        var exec = require("cordova/exec");
        var FileOpener = function() {};

        FileOpener.prototype.open = function(url) {
            exec(null, null, "FileOpener", "openFile", [url]);
        };

        var fileOpener = new FileOpener();
        module.exports = fileOpener;

    });
/**
 * Load Plugin
 */
if (!window.plugins) {
    window.plugins = {};
}
if (!window.plugins.fileOpener) {
    window.plugins.fileOpener = cordova.require("cordova/plugin/fileopener");
}

我已经像这样在 config.xml 页面中添加了插件:

 <plugin name="FileOpener" value="com.phonegap.plugins.file.FileOpener"/>

我在 com.phonegap.plugins.file 包中添加了 FileOpener.java,如下所示:

    package com.phonegap.plugins.file;

     import java.io.File;
     import java.io.FileOutputStream;
     import java.io.IOException;
     import java.io.InputStream;
     import java.net.URL;
     import java.net.URLConnection;

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

     import android.content.Context;
     import android.content.Intent;
     import android.content.pm.PackageManager;
     import android.net.Uri;

     import org.apache.cordova.api.CallbackContext;
     import org.apache.cordova.api.CordovaPlugin;
     import org.apache.cordova.api.PluginResult;

     public class FileOpener extends CordovaPlugin {
      private static final String YOU_TUBE = "youtube.com";
        private static final String ASSETS = "file:///android_asset/";

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) 
               {
        PluginResult.Status status = PluginResult.Status.OK;
        String result = "";

        try {
            if (action.equals("openFile")) {
                openFile(args.getString(0));
            }
            else {
                status = PluginResult.Status.INVALID_ACTION;
            }
            callbackContext.sendPluginResult(new PluginResult(status, result));
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    private void openFile(String url) throws IOException {

        if (url.contains("bit.ly/") || url.contains("goo.gl/") || url.contains("tinyurl.com/") || url.contains("youtu.be/")) {
            //support for google / bitly / tinyurl / youtube shortens
            URLConnection con = new URL(url).openConnection();
            con.connect();
            InputStream is = con.getInputStream();
            //new redirected url
            url = con.getURL().toString();
            is.close();
        }
        // Create URI
        Uri uri = Uri.parse(url);

        Intent intent = null;
        // Check what kind of file you are trying to open, by comparing the url with extensions.
        // When the if condition is matched, plugin sets the correct intent (mime) type, 
        // so Android knew what application to use to open the file
        if (url.contains(YOU_TUBE)) {
            // If we don't do it this way you don't have the option for youtube
            uri = Uri.parse("vnd.youtube:" + uri.getQueryParameter("v"));
            if (isYouTubeInstalled()) {
                intent = new Intent(Intent.ACTION_VIEW, uri);
            } else {
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("market://details?id=com.google.android.youtube"));
            }
        } else if(url.contains(ASSETS)) {
             // get file path in assets folder
            String filepath = url.replace(ASSETS, "");
            // get actual filename from path as command to write to internal storage doesn't like folders
            String filename = filepath.substring(filepath.lastIndexOf("/")+1, filepath.length());

            // Don't copy the file if it already exists
            File fp = new File(this.cordova.getActivity().getFilesDir() + "/" + filename);
            if (!fp.exists()) {
                this.copy(filepath, filename);
            }
            // change uri to be to the new file in internal storage
            uri = Uri.parse("file://" + this.cordova.getActivity().getFilesDir() + "/" + filename);

            if (url.contains(".doc") || url.contains(".docx")) {
                // Word document
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "application/msword");
            } else if(url.contains(".pdf")) {
                // PDF file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "application/pdf");
            } else if(url.contains(".ppt") || url.contains(".pptx")) {
                // Powerpoint file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
            } else if(url.contains(".xls") || url.contains(".xlsx")) {
                // Excel file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "application/vnd.ms-excel");
            } else if(url.contains(".rtf")) {
                // RTF file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "application/rtf");
            } else if(url.contains(".wav")) {
                // WAV audio file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "audio/x-wav");
            } else if(url.contains(".gif")) {
                // GIF file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "image/gif");
            } else if(url.contains(".jpg") || url.contains(".jpeg")) {
                // JPG file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "image/jpeg");
            } else if(url.contains(".txt")) {
                // Text file
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "text/plain");
            } else if(url.contains(".mpg") || url.contains(".mpeg") || url.contains(".mpe") || url.contains(".mp4") || url.contains(".avi")) {
                // Video files
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "video/*");
            }         

            //if you want you can also define the intent type for any other file

            //additionally use else clause below, to manage other unknown extensions
            //in this case, Android will show all applications installed on the device
            //so you can choose which application to use

            else {
                intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "*/*");
            }

        }else {           
        if (url.contains(".doc") || url.contains(".docx")) {
            // Word document
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/msword");
        } else if(url.contains(".pdf")) {
            // PDF file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/pdf");
        } else if(url.contains(".ppt") || url.contains(".pptx")) {
            // Powerpoint file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
        } else if(url.contains(".xls") || url.contains(".xlsx")) {
            // Excel file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/vnd.ms-excel");
        } else if(url.contains(".rtf")) {
            // RTF file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/rtf");
        } else if(url.contains(".wav")) {
            // WAV audio file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "audio/x-wav");
        } else if(url.contains(".gif")) {
            // GIF file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "image/gif");
        } else if(url.contains(".jpg") || url.contains(".jpeg")) {
            // JPG file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "image/jpeg");
        } else if(url.contains(".txt")) {
            // Text file
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "text/plain");
        } else if(url.contains(".mpg") || url.contains(".mpeg") || url.contains(".mpe") || url.contains(".mp4") || url.contains(".avi")) {
            // Video files
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "video/*");
        }         

        //if you want you can also define the intent type for any other file

        //additionally use else clause below, to manage other unknown extensions
        //in this case, Android will show all applications installed on the device
        //so you can choose which application to use

        else {
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "*/*");
        }
        }

        this.cordova.getActivity().startActivity(intent);
    }


    private void copy(String fileFrom, String fileTo) throws IOException {
        // get file to be copied from assets
        InputStream in = this.cordova.getActivity().getAssets().open(fileFrom);
        // get file where copied too, in internal storage.
        // must be MODE_WORLD_READABLE or Android can't play it
        FileOutputStream out = this.cordova.getActivity().openFileOutput(fileTo, Context.MODE_WORLD_READABLE);

        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
            out.write(buf, 0, len);
        in.close();
        out.close();
    }

    private boolean isYouTubeInstalled() {
        PackageManager pm = this.cordova.getActivity().getPackageManager();
        try {
            pm.getPackageInfo("com.google.android.youtube", PackageManager.GET_ACTIVITIES);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }
   }

而且我还为 list 文件添加了权限。

现在使用我的 fileopener 插件,在更改 file.java 页面后一切都可以完美打开。(您可以在编辑部分看到)。如果视频、mp3、img 存储在本地或全局,则可以完美打开。如果 pdf 文件存储在 android/asset 文件夹中,那么它会向我显示,但如果它来自网站,则会向我显示错误。

Logcat 在说我:

  07-26 15:11:38.105: E/Web Console(21696): Uncaught Error: Error calling method on NPObject. at file:///android_asset/www/js/cordova-2.7.0.js:857

那么谁能帮我看看我做错了什么?提前致谢。

最佳答案

免责声明:我是 PSPDFKit 的开发者团队

你可以看看https://github.com/PSPDFKit/Cordova-Androidhttps://github.com/PSPDFKit/Cordova-iOS .这两个插件都包装了 PSPDFKit 并允许像查看 PDF 文档一样简单

function showMyDocument() {
    PSPDFKit.showDocument('file://.../document.pdf');
}

文件下载可以通过 Cordova 下载器插件(如 Joram Teusink 所述)或简单地扩展 PSPDFKit 插件本身来完成。我们欢迎对项目的每一个贡献!

关于android - 如何在 android 中使用 jquery 和 phonegap 打开 pdf 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17873452/

有关android - 如何在 android 中使用 jquery 和 phonegap 打开 pdf 文件?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  7. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  8. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  9. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  10. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

随机推荐