4.1.1.1 创建/使用私有活动

私有活动是其他应用程序无法启动的活动,因此它是最安全的活动。

当使用仅在应用程序中使用的活动(私有活动)时,只要你对类使用显示意图,那么你不必担心将它意外发送到任何其他应用程序。 但是,第三方应用程序可能会读取用于启动活动的意图。 因此,如果你将敏感信息放入用于启动活动的意图中,有必要采取对策,来确保它不会被恶意第三方读取。

下面展示了如何创建私有活动的示例代码。

要点(创建活动):

  1. 不要指定taskAffinity

  2. 不要指定launchMode

  3. 将导出属性明确设置为false

  4. 仔细和安全地处理收到的意图,即使意图从相同的应用发送。

  5. 敏感信息可以发送,因为它发送和接收所有同一应用中的信息。

AndroidManifest.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="org.jssec.android.activity.privateactivity" >
  4. <application
  5. android:allowBackup="false"
  6. android:icon="@drawable/ic_launcher"
  7. android:label="@string/app_name" >
  8. <!-- Private activity -->
  9. <!-- *** POINT 1 *** Do not specify taskAffinity -->
  10. <!-- *** POINT 2 *** Do not specify launchMode -->
  11. <!-- *** POINT 3 *** Explicitly set the exported attribute to false. -->
  12. <activity
  13. android:name=".PrivateActivity"
  14. android:label="@string/app_name"
  15. android:exported="false" />
  16. <!-- Public activity launched by launcher -->
  17. <activity
  18. android:name=".PrivateUserActivity"
  19. android:label="@string/app_name"
  20. android:exported="true" >
  21. <intent-filter>
  22. <action android:name="android.intent.action.MAIN" />
  23. <category android:name="android.intent.category.LAUNCHER" />
  24. </intent-filter>
  25. </activity>
  26. </application>
  27. </manifest>

PrivateActivity.java

  1. package org.jssec.android.activity.privateactivity;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.Toast;
  7. public class PrivateActivity extends Activity {
  8. @Override
  9. public void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.private_activity);
  12. // *** POINT 4 *** Handle the received Intent carefully and securely, even though the Intent was sent from the same application.
  13. // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
  14. String param = getIntent().getStringExtra("PARAM");
  15. Toast.makeText(this, String.format("Received param: ¥"%s"", param), Toast.LENGTH_LONG).show();
  16. }
  17. public void onReturnResultClick(View view) {
  18. // *** POINT 5 *** Sensitive information can be sent since it is sending and receiving all within the same application.
  19. Intent intent = new Intent();
  20. intent.putExtra("RESULT", "Sensitive Info");
  21. setResult(RESULT_OK, intent);
  22. finish();
  23. }
  24. }

下面展示如何使用私有活动的示例代码。

要点(使用活动);

  1. 不要为意图设置FLAG_ACTIVITY_NEW_TASK标志来启动活动。

  2. 使用显式意图,以及用于调用相同应用中的活动的特定的类。

  3. 由于目标活动位于同一个应用中,因此只能通过putExtra()发送敏感信息 [1]。

警告:如果不遵守第 1, 2 和 6 点,第三方可能会读到意图。 更多详细信息,请参阅第 4.1.2.2 和 4.1.2.3 节。

  1. 即使数据来自同一应用中的活动,也要小心并安全地处理收到的结果数据。

PrivateUserActivity.java

  1. package org.jssec.android.activity.privateactivity;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.Toast;
  7. public class PrivateUserActivity extends Activity {
  8. private static final int REQUEST_CODE = 1;
  9. @Override
  10. public void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.user_activity);
  13. }
  14. public void onUseActivityClick(View view) {
  15. // *** POINT 6 *** Do not set the FLAG_ACTIVITY_NEW_TASK flag for intents to start an activity.
  16. // *** POINT 7 *** Use the explicit Intents with the class specified to call an activity in the same application.
  17. Intent intent = new Intent(this, PrivateActivity.class);
  18. // *** POINT 8 *** Sensitive information can be sent only by putExtra() since the destination activity is in the same application.
  19. intent.putExtra("PARAM", "Sensitive Info");
  20. startActivityForResult(intent, REQUEST_CODE);
  21. }
  22. @Override
  23. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  24. super.onActivityResult(requestCode, resultCode, data);
  25. if (resultCode != RESULT_OK) return;
  26. switch (requestCode) {
  27. case REQUEST_CODE:
  28. String result = data.getStringExtra("RESULT");
  29. // *** POINT 9 *** Handle the received data carefully and securely,
  30. // even though the data comes from an activity within the same application.
  31. // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."
  32. Toast.makeText(this, String.format("Received result: ¥"%s"", result), Toast.LENGTH_LONG).show();
  33. break;
  34. }
  35. }
  36. }