如何创建其他应用程序(Polaris Office)只能读取的文件?

时间:2013-04-12 14:06:38

标签: android android-intent android-sdcard android-file android-permissions

以下是我在我的应用中尝试做的事情。我下载文件(docx,pptx,pdf,mov等)并将它们存储在File中。下载文件后,我希望用户能够打开并阅读它。 我不希望用户能够修改File

以下是我试图实现这一目标的方法。

            String uri =   nameFileStatic + extension;
            RestClientGetAsFile client = new RestClientGetAsFile(url, getActivity(), uri) {
                @Override
                protected void onPostExecute(File results) {
                    if (results != null) {
                        if (results.exists()) {
                            Uri path = Uri.fromFile(results);
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setDataAndType(path, type); //type
                            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            try {
                                startActivity(intent);
                            } catch (ActivityNotFoundException e) {
                                Toast.makeText(DescriberAttachments.this.getActivity(),
                                        "No Application Available to View file with extension " + extension, Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                }
            };
            client.execute();

基本上,我在AsyncTask实例中下载文件。然后在onPostExecute()方法中,我用Intent打开文件。

现在问题是:在哪里存储文件?这是我试过的:

  • uri = getDir("SLIMS", Context.MODE_WORLD_READABLE ).getAbsolutePath() + "/Attachments/myfile.docx"。在保存文件之前,我总是确保目录存在。
File directoryMain = new File(getDir("SLIMS", Context.MODE_PRIVATE).getAbsolutePath());
directoryMain.mkdir();
File directoryAttachments = new File( getDir("SLIMS",  Context.MODE_PRIVATE).getAbsolutePath() + "/Attachments");
directoryAttachments.mkdir();

不幸的是,之后我无法打开文件...我收到了一条消息错误(来自Polaris Office)但在我的日志中找不到任何相关消息。

  • uri = getFilesDir() + "/Attachments/myfile.docx".我得到了与上一点相同的错误。

  • uri = Environment.getExternalStorageDirectory() + "/Attachments/myfile.docx"。这次我可以在Polaris Office中打开文件,但我无法将File设为只读。我尝试了myFile.setReadOnly()myFile.setReadable(true)myFile.setWritable(false)但我仍然可以在最后修改文件。

所以我想现在我仍然会将这些文件存储在SD卡中,但我对写入权限感到非常恼火。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

在您的应用内创建ContentProvider并启动查看器应用,并引用内容方案,例如content://com.mydomain.myapp/file/filename.jpg

答案 1 :(得分:0)

正如323go建议的那样,我实现了一个ContentProvider。我的代码来自CommonsWare's post

这是我下载文件的代码。下载文件后,我将其保存为“ComingFromSLIMSDatabase”+扩展名。扩展名可以是docx,pptx,pdf等。下载文件后,我调用一个隐含Intent的Activity启动一个Activity,并给出内容Provider的uri。

String uri = nameFileStatic + extension;
            RestClientGetAsFile client = new RestClientGetAsFile(url, getActivity(), uri) {
                @Override
                protected void onPostExecute(File results) {
                    if (results != null) {
                        if (results.exists()) {
                            results.setReadable(true);
                            try {
                                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(AttachmentProvider.CONTENT_URI
                                        + "ComingFromSLIMSDatabase" + extension)));
                            } catch (ActivityNotFoundException e) {
                                Toast.makeText(DescriberAttachments.this.getActivity(),
                                        "No Application Available to View file with extension " + extension, Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                }
            };
            client.execute();

然后ContentProvider捕获该调用并打开我想要显示的文件。

public class FileProvider extends ContentProvider {
  public static final Uri CONTENT_URI=Uri.parse("content://com.commonsware.android.cp.files/");
  private static final HashMap<String, String> MIME_TYPES=new HashMap<String, String>();

  static {
    MIME_TYPES.put(".pdf", "application/pdf");
  }

  @Override
  public boolean onCreate() {
    File f=new File(getContext().getFilesDir(), "test.pdf");

    if (!f.exists()) {
      AssetManager assets=getContext().getResources().getAssets();

      try {
        copy(assets.open("test.pdf"), f);
      }
      catch (IOException e) {
        Log.e("FileProvider", "Exception copying from assets", e);

        return(false);
      }
    }

    return(true);
  }

  @Override
  public String getType(Uri uri) {
    String path=uri.toString();

    for (String extension : MIME_TYPES.keySet()) {
      if (path.endsWith(extension)) {
        return(MIME_TYPES.get(extension));
      }
    }

    return(null);
  }

  @Override
  public ParcelFileDescriptor openFile(Uri uri, String mode)
    throws FileNotFoundException {
    String path = uri.getPath();
    File f=new File(getContext().getFilesDir(),path);
    if (f.exists()) {
      return(ParcelFileDescriptor.open(f,
                                        ParcelFileDescriptor.MODE_READ_ONLY));
    }

    throw new FileNotFoundException(uri.getPath());  
  }

  @Override
  public Cursor query(Uri url, String[] projection, String selection,
                        String[] selectionArgs, String sort) {
    throw new RuntimeException("Operation not supported");
  }

  @Override
  public Uri insert(Uri uri, ContentValues initialValues) {
    throw new RuntimeException("Operation not supported");
  }

  @Override
  public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
    throw new RuntimeException("Operation not supported");
  }

  @Override
  public int delete(Uri uri, String where, String[] whereArgs) {
    throw new RuntimeException("Operation not supported");
  }

  static private void copy(InputStream in, File dst) throws IOException {
    FileOutputStream out=new FileOutputStream(dst);
    byte[] buf=new byte[1024];
    int len;

    while((len=in.read(buf))>0) {
      out.write(buf, 0, len);
    }

    in.close();
    out.close();
  }
}

使用此方法,即使文件存储在Context.getFilesDir()中,用户也可以打开该文件。现在我还是很困惑。因为如果我打开一个doc文件,我仍然可以修改它并将其保存在其他地方。目前它并不是一个理想的功能。

我想知道是否有人知道查看文件内容的方法,而不让其他应用程序将其保存在其他地方