android对PDF文件的操作(上传、预览、下载和转存相册)

android对PDF文件的操作(上传、预览、下载和转存相册)

一、上传PDF文件到服务器

       前段时间有一个老项目需要添加对PDF的上传、下载和预览等操作,我这边完成之后整理发一下博客,因为项目较老,框架技术也不是先进技术。

       上传文件主要使用了OkGo网络请求框架,如果是使用OKhttp的将网络请求代码和回调方法改成相应的即可,因为上传文件需要用到网络请求权限和文件读写权限,记得需要在AndroidManifest.xml中配置:

   <!--用于访问网络-->
   <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <!--用于写入缓存数据到扩展存储卡-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <!--用于读取扩展存储卡文件-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> 

       上传文件代码:

       (1)点击按钮调用打开手机的文件选择器:

 // 打开系统的文件选择器
    public void pickFile(View view) {
        int permission = ActivityCompat.checkSelfPermission(this,
                Manifest.permission.READ_EXTERNAL_STORAGE);//缺少什么权限就写什么权限
        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,}, 0);
        }
        int permission2 = ActivityCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);//缺少什么权限就写什么权限
        if (permission2 != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,}, 0);
        }
        else{
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            //intent.setType("image/*");//选择图片
            //intent.setType("audio/*"); //选择音频
            //intent.setType("video/*"); //选择视频 (mp4 3gp 是android支持的视频格式)
            //intent.setType("video/*;image/*");//同时选择视频和图片
            intent.setType("*/*");//无类型限制
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            startActivityForResult(intent, 1);
        }
    }

       (2)回调方法获取文件的真实路径,根据android的版本不同,采用不同的方法

  // 获取文件的真实路径
    String path;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            Uri uri = data.getData();
            if ("file".equalsIgnoreCase(uri.getScheme())) {//使用第三方应用打开
                path = uri.getPath();
                ShowDiglog(path);
                System.out.println("获得地址1"+path);
                return;
            }
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后
                path = getPath(this, uri);
                System.out.println("获得地址2"+path);
                ShowDiglog(path);
            } else {//4.4以下下系统调用方法
                path = getRealPathFromURI(uri);
                System.out.println("获得地址3"+path);
                ShowDiglog(path);
            }
        }
    }

    public String getRealPathFromURI(Uri contentUri) {
        String res = null;
        String[] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
        if (null != cursor && cursor.moveToFirst()) {
            ;
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            res = cursor.getString(column_index);
            cursor.close();
        }
        return res;
    }

    /**
     * 专为Android4.4设计的从Uri获取文件绝对路径,以前的方法已不好使
     */
    @SuppressLint("NewApi")
    public String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public String getDataColumn(Context context, Uri uri, String selection,
                                String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

       (3)点击弹窗的上传按钮,调用网络接口,实现文件上传

public void ShowDiglog(final String path){
        MyAlertDialog myAlertDialog = new MyAlertDialog(this).builder()
                .setTitle("上传简历?")
                .setMsg(path)
                .setPositiveButton("上传", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        uploadFile(path);
                        System.out.println("上传");
                   }
               }).setNegativeButton("取消", new View.OnClickListener() {
                   @Override
                   public void onClick(View v) {
                       System.out.println("取消");
                   }
               });
       myAlertDialog.show();
}
public void uploadFile(String path){
        File file = new File(path);
        OkGo.<String>post(NetUrl.DNS + NetUrl.UploadCv)
                .tag(this)
                .params("file", file)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        try {
                            JSONObject jsonObject = new JSONObject(response.body());
                            System.out.println("输出结果"+jsonObject);
                            int infoCode = jsonObject.getInt("status");
                            if (infoCode == 0) {
                                Tools.toast(IntroFileActivity.this, "简历上传成功!");
                                introAdapter.clear();
                                pageNumber = 1;
                                initData(pageNumber);
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }

二、预览网络上的PDF文件

       因为android原生无法直接预览PDF文件,所有简单的就是将PDF文件下载下来转成图片进行预览,但是这样子下载到用户的手机中对用户不友好。在考虑之后,决定抵赖第三方的依赖来实现,需要引入pdfviewpager组件,在gradle组件中添加以下代码:

       (1)添加依赖:

    //预览pdf文件
    compile('es.voghdev.pdfviewpager:library:1.0.3') {
        exclude module: 'support-v4'
        exclude group: 'com.android.support'
    }

       (2)界面设计(引入依赖的界面组件):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ptr="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/theme_background"
    android:orientation="vertical">

    <!-- toolbar菜单 -->

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/tj_toolbar_height"
        android:background="@color/tj_toolbar_background"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/toolbar_back"
            android:layout_width="50dp"
            android:layout_height="match_parent"
            android:background="@drawable/tj_click_selector"
            android:contentDescription="@null"
            android:scaleType="center"
            android:src="@drawable/btn_navbar_back" />

        <TextView
            android:id="@+id/toolbar_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="@string/activity_invoice_file_title"
            android:textColor="@color/tj_toolbar_title"
            android:textSize="@dimen/tj_toolbar_title" />

        <TextView
            android:id="@+id/textView_download"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:background="@drawable/tj_click_selector"
            android:gravity="center"
            android:text="@string/activity_invoice_file_download"
            android:textColor="@color/tj_text_content_d"
            android:textSize="16sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1px"
            android:layout_alignParentBottom="true"
            android:background="@color/tj_device_line_2" />
    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/remote_pdf_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <es.voghdev.pdfviewpager.library.PDFViewPager
            android:id="@+id/pdfViewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </RelativeLayout>

    <ProgressBar
        android:id="@+id/pb_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_gravity="center" />
</LinearLayout>

       显示效果如图,实际手机中不会有PDF图标:

在这里插入图片描述

       (3)Activity代码:

public class ActivityInvoiceFile extends AppCompatActivity implements  DownloadFile.Listener,OnClickListener {

    private RelativeLayout pdf_root;
    private ProgressBar pb_bar;
    private TextView TextViewDownload;
    private RemotePDFViewPager remotePDFViewPager;
    private String pdfUrl = "";
    private String invoiceNo = "";
    private PDFPagerAdapter adapter;
    private Context mContext;
    private String destFileDir;
    private String destFileName;
    protected RequestCall mRequest;
    private ProgressDialog progressDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_invoice_file);
        mContext = ActivityInvoiceFile.this;

        setupView();

        setupData();

        setDownloadListener();
    }

    private void setupView() {
        findViewById(R.id.toolbar_back).setOnClickListener(this);
        pdf_root = (RelativeLayout) findViewById(R.id.remote_pdf_root);
        pb_bar = (ProgressBar) findViewById(R.id.pb_bar);
    }

    protected void setupData() {
        Intent intent = getIntent();
        //pdfUrl 为文件地址,比如www.xxx.com/file/xxx.pdf
        pdfUrl = intent.getStringExtra("pdfUrl");
    }

    /*设置监听*/
    protected void setDownloadListener() {
        final DownloadFile.Listener listener = this;
        remotePDFViewPager = new RemotePDFViewPager(this, pdfUrl, listener);
        remotePDFViewPager.setId(R.id.pdfViewPager);
    }

    /*加载成功调用*/
    @Override
    public void onSuccess(String url, String destinationPath) {
        pb_bar.setVisibility(View.GONE);
        adapter = new PDFPagerAdapter(this, FileUtil.extractFileNameFromURL(url));
        remotePDFViewPager.setAdapter(adapter);
        updateLayout();
    }

    /*更新视图*/
    private void updateLayout() {
        pdf_root.removeAllViewsInLayout();
        pdf_root.addView(remotePDFViewPager, LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
    }

    /*加载失败调用*/
    @Override
    public void onFailure(Exception e) {
        pb_bar.setVisibility(View.GONE);
        Toast.makeText(mContext, "文件加载失败", Toast.LENGTH_SHORT).show();
    }
}

三、PDF文件的下载和转存相册

       其实下载文件倒是简单,就是简单的文件下载方式,这里附上一个文件下载工具类,对异常处理和回调进行封装。

       (1)文件下载工具类:

/**
 * 文件下载工具类(单例模式)
 */

public class DownloadUtil {
    private static DownloadUtil downloadUtil;
    private final OkHttpClient okHttpClient;

    public static DownloadUtil get() {
        if (downloadUtil == null) {
            downloadUtil = new DownloadUtil();
        }
        return downloadUtil;
    }

    private DownloadUtil() {
        okHttpClient = new OkHttpClient();
    }

    /**
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称
     * @param listener     下载监听
     */
    public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {
        Request request = new Request.Builder().url(url).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 下载失败监听回调
                listener.onDownloadFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                // 储存下载文件的目录
                File dir = new File(destFileDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, destFileName);
                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        // 下载中更新进度条
                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    // 下载完成
                    listener.onDownloadSuccess(file);
                } catch (Exception e) {
                    listener.onDownloadFailed(e);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }
        });
    }

    public interface OnDownloadListener {
        /**
         * @param file 下载成功后的文件
         */
        void onDownloadSuccess(File file);

        /**
         * @param progress 下载进度
         */
        void onDownloading(int progress);

        /**
         * @param e 下载异常信息
         */
        void onDownloadFailed(Exception e);
    }
}

       (2)文件下载和转存相册

       在文件下载之后,回调方法返回其真实路径,通过真实路径获取到PDF文件,并将其转成Bitmap,在进一步保存图片到手机中,最后将图片文件插入到系统图库,实现了转存相册功能。Activity完整代码如下:

public class ActivityInvoiceFile extends AppCompatActivity implements  DownloadFile.Listener,OnClickListener {

    private RelativeLayout pdf_root;
    private ProgressBar pb_bar;
    private TextView TextViewDownload;
    private RemotePDFViewPager remotePDFViewPager;
    private String pdfUrl = "";
    private String invoiceNo = "";
    private PDFPagerAdapter adapter;
    private Context mContext;
    private String destFileDir;
    private String destFileName;
    protected RequestCall mRequest;
    private ProgressDialog progressDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_invoice_file);
        mContext = ActivityInvoiceFile.this;

        setupView();

        setupData();

        setDownloadListener();
    }

    private void setupView() {
        findViewById(R.id.toolbar_back).setOnClickListener(this);
        pdf_root = (RelativeLayout) findViewById(R.id.remote_pdf_root);
        pb_bar = (ProgressBar) findViewById(R.id.pb_bar);
        TextViewDownload = (TextView)findViewById(R.id.textView_download);
        TextViewDownload.setOnClickListener(this);
    }

    protected void setupData() {
        Intent intent = getIntent();
        pdfUrl = intent.getStringExtra("pdfUrl");
        invoiceNo = intent.getStringExtra("invoiceNo");
    }

    /*设置监听*/
    protected void setDownloadListener() {
        final DownloadFile.Listener listener = this;
        remotePDFViewPager = new RemotePDFViewPager(this, pdfUrl, listener);
        remotePDFViewPager.setId(R.id.pdfViewPager);
    }

    /*加载成功调用*/
    @Override
    public void onSuccess(String url, String destinationPath) {
        pb_bar.setVisibility(View.GONE);
        adapter = new PDFPagerAdapter(this, FileUtil.extractFileNameFromURL(url));
        remotePDFViewPager.setAdapter(adapter);
        updateLayout();
    }

    /*更新视图*/
    private void updateLayout() {
        pdf_root.removeAllViewsInLayout();
        pdf_root.addView(remotePDFViewPager, LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
    }

    /*加载失败调用*/
    @Override
    public void onFailure(Exception e) {
        pb_bar.setVisibility(View.GONE);
        Toast.makeText(mContext, "文件加载失败", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProgressUpdate(int progress, int total) {
    }
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
            case R.id.toolbar_back:
                finish();
                break;
            case R.id.textView_download:
                downFile(pdfUrl);
                break;
            default:
                break;
        }
    }
    /**
     * 文件下载
     *
     * @param url
     */
    public void downFile(String url) {
        progressDialog = new ProgressDialog(ActivityInvoiceFile.this);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setProgress(0);
        progressDialog.setMax(100);
        progressDialog.show();
        progressDialog.setCancelable(true);
        DownloadUtil.get().download(url, Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"Invoices", "Invoice"+invoiceNo+".pdf", new DownloadUtil.OnDownloadListener() {
            @Override
            public void onDownloadSuccess(File file) {
                if (progressDialog != null && progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }
                Looper.prepare();//增加部分
                    AlertsavePhoto("已下载至手机内部存储设备根目录下Invoices文件夹中","是否转存图片至相册?",file);
                Looper.loop();//增加部分
            }

            @Override
            public void onDownloading(int progress) {
                progressDialog.setProgress(progress);
            }

            @Override
            public void onDownloadFailed(Exception e) {
                if (progressDialog != null && progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }
                Looper.prepare();//增加部分
                    Toast.makeText(mContext, "文件下载失败", Toast.LENGTH_SHORT).show();
                Looper.loop();//增加部分
            }
        });
    }
    //转存图片对话框
    private void AlertsavePhoto(String title, String msg, final File file) {
        new Builder(mContext)
                .setTitle(title)
                .setMessage(msg)
                .setNegativeButton(android.R.string.cancel, null)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        ArrayList<Bitmap> bitmap = pdfToBitmap(file);
                        saveImageToGallery(mContext,bitmap);
                    }
                })
                .create()
                .show();
    }

    //PDF转成Bitmap
    private ArrayList<Bitmap> pdfToBitmap(File pdfFile) {
        ArrayList<Bitmap> bitmaps = new ArrayList<>();
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));
                Bitmap bitmap;
                final int pageCount = renderer.getPageCount();
                Log.e("test_sign", "图片de 张数: " +pageCount);
                for (int i = 0; i < pageCount; i++) {
                    PdfRenderer.Page page = renderer.openPage(i);
                    int width = getResources().getDisplayMetrics().densityDpi / 72 * page.getWidth();
                    int height = getResources().getDisplayMetrics().densityDpi / 72 * page.getHeight();
                    bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                    //todo 以下三行处理图片存储到本地出现黑屏的问题,这个涉及到背景问题
                    Canvas canvas = new Canvas(bitmap);
                    canvas.drawColor(Color.WHITE);
                    canvas.drawBitmap(bitmap, 0, 0, null);
                    Rect r = new Rect(0, 0, width, height);
                    page.render(bitmap, r, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
                    bitmaps.add(bitmap);
                    // close the page
                    page.close();
                }
                // close the renderer
                renderer.close();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return bitmaps;

    }
    private void saveImageToGallery(Context context, ArrayList<Bitmap> bitmaps) {
        // 首先保存图片
        File appDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "InvoicePhoto");
        for (int i = 0; i < bitmaps.size(); i++) {
            if (!appDir.exists()) {
                appDir.mkdir();
            }
            String fileName = System.currentTimeMillis() + ".jpg";
            File file = new File(appDir, fileName);
            Log.e("test_sign", "图片全路径localFile = " + appDir.getAbsolutePath() + fileName);
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(file);
                bitmaps.get(i).compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.flush();
                fos.close();
            } catch (FileNotFoundException e) {
                Toast.makeText(mContext, "保存到相册失败!", Toast.LENGTH_LONG).show();
                e.printStackTrace();
            } catch (IOException e) {
                Toast.makeText(mContext, "保存到相册失败!", Toast.LENGTH_LONG).show();
                e.printStackTrace();
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                        //回收
                        bitmaps.get(i).recycle();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 其次把文件插入到系统图库
            try {
                MediaStore.Images.Media.insertImage(context.getContentResolver(),
                        file.getAbsolutePath(), fileName, null);
            } catch (FileNotFoundException e) {
                Toast.makeText(mContext, "保存到相册失败!", Toast.LENGTH_LONG).show();
                e.printStackTrace();
            }
        }
        Toast.makeText(mContext, "已保存到手机相册!", Toast.LENGTH_LONG).show();
        // 最后通知图库更新
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                Uri.fromFile(new File(appDir.getPath()))));
    }

}

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是两种在Android预览PDF文件的方法: 1. 使用Android PdfViewer库 Android PdfViewer是一个开源库,可以在Android应用中实现PDF文件预览。你可以通过在项目的build.gradle文件中添加依赖来使用该库: ```groovy implementation 'com.github.barteksc:android-pdf-viewer:2.8.2' ``` 然后,在你的Activity中,你可以使用PdfView来加载和显示PDF文件: ```java import com.github.barteksc.pdfviewer.PDFView; public class MainActivity extends AppCompatActivity { private PDFView pdfView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pdfView = findViewById(R.id.pdfView); pdfView.fromAsset("sample.pdf") // 从assets文件夹加载PDF文件 .load(); } } ``` 在上面的代码中,我们假设你的项目中有一个名为"sample.pdf"的PDF文件放在assets文件夹中。你可以根据实际情况修改文件名和路径。 2. 使用Mozilla的PDF.js库 PDF.js是一个由Mozilla开发的JavaScript库,可以在Web浏览器中预览PDF文件。你可以将PDF.js集成到你的Android应用中,通过WebView加载并显示PDF文件。首先,你需要将PDF.js库文件添加到你的项目中。你可以从GitHub上下载PDF.js库文件,并将其放置在你的项目的assets文件夹中。然后,在你的Activity中,你可以使用WebView来加载PDF.js库文件PDF文件: ```java import android.os.Bundle; import android.webkit.WebSettings; import android.webkit.WebView; public class MainActivity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webView.loadUrl("file:///android_asset/pdfjs/web/viewer.html?file=sample.pdf"); } } ``` 在上面的代码中,我们假设你将PDF.js库文件放在了assets文件夹的"pdfjs"子文件夹中,并且你的项目中有一个名为"sample.pdf"的PDF文件。你可以根据实际情况修改文件名和路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值