阿里巴巴Android开发手册

摘自阿里巴巴Android开发手册

强制要求的

  • 1. Activity 间的数据通信,对于数据量比较大的,避免使用 intent + Parcelable 的方式,可以考虑 EventBus等替代方案,以免造成 TransationTooLargeException
  • 2. Activity 间通过隐士 Intent的跳转,在发出 Intent 之前必须通过 resolveActivity 检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      public void viewUrl(String url, String mimeType) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(Uri.parse(url), mimeType);
    if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_
    ONLY) != null) {
    startActivity(intent);
    }else {
    // 找不到指定的 Activity
    }
    }

而不应该:

1
2
3
4
5
6
7
Intent intent = new Intent();
intent.setAction("com.example.DemoIntent ");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}

  • 3. 避免在Service#onStartCommand/onBind()方法中执行耗时操作,如果确实有需求,应采用IntentService 或采用其他异步机制完成。
    正例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    }
    public void startIntentService(View source) {
    Intent intent = new Intent(this, MyIntentService.class);
    startService(intent);
    }
    }
    public class MyIntentService extends IntentService {
    public MyIntentService() {
    super("MyIntentService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
    synchronized (this) {
    try {
    ......
    } catch (Exception e) {
    }
    }
    }
    }
  • 4. 避免在 BroadcastReceive#onReceive()中执行耗时操作,如果有耗时工作,应该创建 IntentService完成,而不应该在BroadcastReceiver 内创建子线程去做。

说明:
由于该方法是在主线程执行,如果执行耗时操作会导致 UI 不流畅,可以使用 IntentService,创建 HanlderThread 或者调用 Context#registerReceiver(BroadcastReceiver,IntentFitter,String,Handler) 方法等方式,在其他 Worker 线程执行 onReceive.BroadcastReceiver#onReceive() 方法耗时超过10秒钟,可能会被系统杀死。
正例:

1
2
3
4
5
6
7
8
9
10
11
IntentFilter filter = new IntentFilter();
filter.addAction(LOGIN_SUCCESS);
this.registerReceiver(mBroadcastReceiver, filter);
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Intent userHomeIntent = new Intent();
userHomeIntent.setClass(this, UserHomeService.class);
this.startService(userHomeIntent);
}
};

反例:

1
2
3
4
5
6
7
8
9
mBroadcastReceiver = new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
MyDatabaseHelper myDB = new MyDatabaseHelper(context);
myDB.initData();
// have more database operation here
}
};

  • 5. 避免使用隐士 Intent 广播敏感信息,信息可能被其他注册了对应 BroadcastReceiver 的App接收。

说明:
通过Context#sendBroadcast()发送的隐士广播会被感兴趣的 receiver 接收,恶意应用注册监听该广播的 receiver可能会获取到 Intent 中传递的敏感信息,并进行其他危险操作。如果发送的广播为使用 Context#sendOrderedBroadcast()方法发送的有序广播,优先级较高的恶意 receiver可能直接丢弃该广播,造成服务不可用,或者向广播结果塞入恶意数据。

如果广播仅限于应用内,则可以是iyongLocalBroadcastManager#sendBroadcast()实现,避免敏感信息外泄和intent拦截的风险。

正例:

1
2
3
Intent intent = new Intent("my-sensitive-event");
intent.putExtra("event", "this is a test event");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

反例:

1
2
3
4
5
6
7
8
9
10
11
Intent intent = new Intent();
v1.setAction("com.sample.action.server_running");
v1.putExtra("local_ip", v0.h);
v1.putExtra("port", v0.i);
v1.putExtra("code", v0.g);
v1.putExtra("connected", v0.s);
v1.putExtra("pwd_predefined", v0.r);
if (!TextUtils.isEmpty(v0.t)) {
v1.putExtra("connected_usr", v0.t);
}
context.sendBroadcast(v1);

以上广播可能被其他应用的如下 receiver 接收导致敏感信息泄露:

1
2
3
4
5
6
7
8
9
10
11
12
13
final class MyReceiver extends BroadcastReceiver {
public final void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction() != null) {
String s = intent.getAction();
if (s.equals("com.sample.action.server_running") {
String ip = intent.getStringExtra("local_ip");
String pwd = intent.getStringExtra("code");
String port = intent.getIntExtra("port", 8888);
boolean status = intent.getBooleanExtra("connected", false);
}
}
}
}

-------------本文结束感谢您的阅读-------------