You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android技术问询:Intent启动的系统联系人选择屏无法存活屏幕旋转

解决屏幕旋转时通讯录选择界面被销毁的问题

这个坑我之前踩过!核心原因是屏幕旋转触发了你的宿主Activity销毁重建,系统会判定之前启动的通讯录选择界面的上下文已经失效,直接把它关掉,让你回到应用。下面给你两个解决方案,优先选第一个,能完美解决问题:

方案一:阻止Activity在屏幕旋转时重启(最优)

通过简单配置让Activity忽略屏幕旋转这类配置变化,保持实例存活,这样通讯录选择界面就不会因为宿主Activity重启被强制关闭了。

  1. 修改AndroidManifest.xml里的Activity配置
    找到你发起保存联系人操作的Activity标签,加上android:configChanges属性,把旋转相关的配置项都包含进去:
<activity
    android:name=".YourSaveContactActivity"
    <!-- 新增这行配置 -->
    android:configChanges="orientation|screenSize|smallestScreenSize" />
  • orientation:捕获屏幕横/竖屏切换
  • screenSize/smallestScreenSize:Android 3.2+必须加,因为旋转时屏幕尺寸的逻辑值会跟着变,不加的话系统还是会重启Activity
  1. 重写onConfigurationChanged方法处理UI更新
    因为Activity不再自动重建,你得手动处理旋转后的UI适配,比如重新加载布局、绑定视图:
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // 重新加载布局适配新方向
    setContentView(R.layout.activity_save_contact);
    // 重新初始化按钮、输入框这些组件,恢复之前的输入状态
    initViews();
}

方案二:用Activity Result API+ViewModel恢复状态(备选)

如果你不想阻止Activity重启,可以用ViewModel保存请求状态,在Activity重建后自动重新拉起选择界面。不过这种方式会让用户重新看到选择界面,之前的操作状态没法保留,只能作为备选方案:

  1. 写个ViewModel存状态
public class SaveContactViewModel extends ViewModel {
    private final MutableLiveData<Intent> pendingContactIntent = new MutableLiveData<>();

    public void setPendingIntent(Intent intent) {
        pendingContactIntent.setValue(intent);
    }

    public LiveData<Intent> getPendingIntent() {
        return pendingContactIntent;
    }
}
  1. 在Activity里结合使用ViewModel和Activity Result API
private SaveContactViewModel viewModel;
private ActivityResultLauncher<Intent> createContactLauncher;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_save_contact);

    viewModel = new ViewModelProvider(this).get(SaveContactViewModel.class);
    createContactLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == RESULT_OK) {
                // 处理保存成功的逻辑
                viewModel.setPendingIntent(null); // 清除待处理状态
            }
        });

    // 重建后自动检查有没有未完成的保存请求,有就重新拉起界面
    viewModel.getPendingIntent().observe(this, intent -> {
        if (intent != null) {
            createContactLauncher.launch(intent);
        }
    });
}

// 点击保存联系人按钮的逻辑
public void onSaveContactClick(View view) {
    Intent intent = new Intent(Intent.ACTION_INSERT);
    intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
    intent.putExtra(ContactsContract.Intents.Insert.NAME, "测试联系人");
    intent.putExtra(ContactsContract.Intents.Insert.PHONE, "13800138000");
    
    viewModel.setPendingIntent(intent); // 把请求状态存起来
    createContactLauncher.launch(intent);
}

小提醒

  • 优先选方案一,能让用户旋转屏幕后继续在通讯录选择界面操作,完全不用重新来
  • 如果你还在使用旧版的startActivityForResult方法,建议赶紧迁移到ActivityResultContracts API,它对配置变化的兼容性好很多

内容的提问来源于stack exchange,提问作者DarthDonut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:37:44