4.6.1.2 使用公共只读文件

这是使用文件向未指定的大量应用公开内容的情况。 如果通过遵循以下几点来实现,那么它也是比较安全的文件使用方法。 请注意,在 API 级别 1 7及更高版本中,不推荐使用MODE_WORLD_READABLE变量来创建公共文件,并且在 API 级别 24 及更高版本中,会触发安全异常; 因此使用内容供应器的文件共享方法更可取。

要点:

  1. 文件必须在应用目录中创建。

  2. 文件的访问权限必须设置为其他应用只读。

  3. 敏感信息不得存储。

  4. 对于要存储在文件中的信息,请仔细和安全地处理文件数据。

PublicFileActivity.java

  1. package org.jssec.android.file.publicfile.readonly;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import android.app.Activity;
  8. import android.os.Bundle;
  9. import android.view.View;
  10. import android.widget.TextView;
  11. public class PublicFileActivity extends Activity {
  12. private TextView mFileView;
  13. private static final String FILE_NAME = "public_file.dat";
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.file);
  18. mFileView = (TextView) findViewById(R.id.file_view);
  19. }
  20. /**
  21. * Create file process
  22. *
  23. * @param view
  24. */
  25. public void onCreateFileClick(View view) {
  26. FileOutputStream fos = null;
  27. try {
  28. // *** POINT 1 *** Files must be created in application directory.
  29. // *** POINT 2 *** The access privilege of file must be set to read only to other applications.
  30. // (MODE_WORLD_READABLE is deprecated API Level 17,
  31. // don't use this mode as much as possible and exchange data by using ContentProvider().)
  32. fos = openFileOutput(FILE_NAME, MODE_WORLD_READABLE);
  33. // *** POINT 3 *** Sensitive information must not be stored.
  34. // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
  35. // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
  36. fos.write(new String("Not sensitive information (Public File Activity)¥n").getBytes());
  37. } catch (FileNotFoundException e) {
  38. mFileView.setText(R.string.file_view);
  39. } catch (IOException e) {
  40. android.util.Log.e("PublicFileActivity", "failed to read file");
  41. } finally {
  42. if (fos != null) {
  43. try {
  44. fos.close();
  45. } catch (IOException e) {
  46. android.util.Log.e("PublicFileActivity", "failed to close file");
  47. }
  48. }
  49. }
  50. finish();
  51. }
  52. /**
  53. * Read file process
  54. *
  55. * @param view
  56. */
  57. public void onReadFileClick(View view) {
  58. FileInputStream fis = null;
  59. try {
  60. fis = openFileInput(FILE_NAME);
  61. byte[] data = new byte[(int) fis.getChannel().size()];
  62. fis.read(data);
  63. String str = new String(data);
  64. mFileView.setText(str);
  65. } catch (FileNotFoundException e) {
  66. mFileView.setText(R.string.file_view);
  67. } catch (IOException e) {
  68. android.util.Log.e("PublicFileActivity", "failed to read file");
  69. } finally {
  70. if (fis != null) {
  71. try {
  72. fis.close();
  73. } catch (IOException e) {
  74. android.util.Log.e("PublicFileActivity", "failed to close file");
  75. }
  76. }
  77. }
  78. }
  79. /**
  80. * Delete file process
  81. *
  82. * @param view
  83. */
  84. public void onDeleteFileClick(View view) {
  85. File file = new File(this.getFilesDir() + "/" + FILE_NAME);
  86. file.delete();
  87. mFileView.setText(R.string.file_view);
  88. }
  89. }

PublicUserActivity.java

  1. package org.jssec.android.file.publicuser.readonly;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import android.app.Activity;
  8. import android.content.ActivityNotFoundException;
  9. import android.content.Context;
  10. import android.content.Intent;
  11. import android.content.pm.PackageManager.NameNotFoundException;
  12. import android.os.Bundle;
  13. import android.view.View;
  14. import android.widget.TextView;
  15. public class PublicUserActivity extends Activity {
  16. private TextView mFileView;
  17. private static final String TARGET_PACKAGE = "org.jssec.android.file.publicfile.readonly";
  18. private static final String TARGET_CLASS = "org.jssec.android.file.publicfile.readonly.PublicFileActivity";
  19. private static final String FILE_NAME = "public_file.dat";
  20. @Override
  21. public void onCreate(Bundle savedInstanceState) {
  22. super.onCreate(savedInstanceState);
  23. setContentView(R.layout.user);
  24. mFileView = (TextView) findViewById(R.id.file_view);
  25. }
  26. private void callFileActivity() {
  27. Intent intent = new Intent();
  28. intent.setClassName(TARGET_PACKAGE, TARGET_CLASS);
  29. try {
  30. startActivity(intent);
  31. } catch (ActivityNotFoundException e) {
  32. mFileView.setText("(File Activity does not exist)");
  33. }
  34. }
  35. /**
  36. * Call file Activity process
  37. *
  38. * @param view
  39. */
  40. public void onCallFileActivityClick(View view) {
  41. callFileActivity();
  42. }
  43. /**
  44. * Read file process
  45. *
  46. * @param view
  47. */
  48. public void onReadFileClick(View view) {
  49. FileInputStream fis = null;
  50. try {
  51. File file = new File(getFilesPath(FILE_NAME));
  52. fis = new FileInputStream(file);
  53. byte[] data = new byte[(int) fis.getChannel().size()];
  54. fis.read(data);
  55. // *** POINT 4 *** Regarding the information to be stored in files, handle file data carefully and securely.
  56. // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
  57. String str = new String(data);
  58. mFileView.setText(str);
  59. } catch (FileNotFoundException e) {
  60. android.util.Log.e("PublicUserActivity", "no file");
  61. } catch (IOException e) {
  62. android.util.Log.e("PublicUserActivity", "failed to read file");
  63. } finally {
  64. if (fis != null) {
  65. try {
  66. fis.close();
  67. } catch (IOException e) {
  68. android.util.Log.e("PublicUserActivity", "failed to close file");
  69. }
  70. }
  71. }
  72. }
  73. /**
  74. * Rewrite file process
  75. *
  76. * @param view
  77. */
  78. public void onWriteFileClick(View view) {
  79. FileOutputStream fos = null;
  80. boolean exception = false;
  81. try {
  82. File file = new File(getFilesPath(FILE_NAME));
  83. // Fail to write in. FileNotFoundException occurs.
  84. fos = new FileOutputStream(file, true);
  85. fos.write(new String("Not sensitive information (Public User Activity)¥n").getBytes());
  86. } catch (IOException e) {
  87. mFileView.setText(e.getMessage());
  88. exception = true;
  89. } finally {
  90. if (fos != null) {
  91. try {
  92. fos.close();
  93. } catch (IOException e) {
  94. exception = true;
  95. }
  96. }
  97. }
  98. if (!exception)
  99. callFileActivity();
  100. }
  101. private String getFilesPath(String filename) {
  102. String path = "";
  103. try {
  104. Context ctx = createPackageContext(TARGET_PACKAGE,
  105. Context.CONTEXT_RESTRICTED);
  106. File file = new File(ctx.getFilesDir(), filename);
  107. path = file.getPath();
  108. } catch (NameNotFoundException e) {
  109. android.util.Log.e("PublicUserActivity", "no file");
  110. }
  111. return path;
  112. }
  113. }