Android技术问询:Intent启动的系统联系人选择屏无法存活屏幕旋转
解决屏幕旋转时通讯录选择界面被销毁的问题
这个坑我之前踩过!核心原因是屏幕旋转触发了你的宿主Activity销毁重建,系统会判定之前启动的通讯录选择界面的上下文已经失效,直接把它关掉,让你回到应用。下面给你两个解决方案,优先选第一个,能完美解决问题:
方案一:阻止Activity在屏幕旋转时重启(最优)
通过简单配置让Activity忽略屏幕旋转这类配置变化,保持实例存活,这样通讯录选择界面就不会因为宿主Activity重启被强制关闭了。
- 修改
AndroidManifest.xml里的Activity配置
找到你发起保存联系人操作的Activity标签,加上android:configChanges属性,把旋转相关的配置项都包含进去:
<activity android:name=".YourSaveContactActivity" <!-- 新增这行配置 --> android:configChanges="orientation|screenSize|smallestScreenSize" />
orientation:捕获屏幕横/竖屏切换screenSize/smallestScreenSize:Android 3.2+必须加,因为旋转时屏幕尺寸的逻辑值会跟着变,不加的话系统还是会重启Activity
- 重写
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重建后自动重新拉起选择界面。不过这种方式会让用户重新看到选择界面,之前的操作状态没法保留,只能作为备选方案:
- 写个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; } }
- 在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方法,建议赶紧迁移到ActivityResultContractsAPI,它对配置变化的兼容性好很多
内容的提问来源于stack exchange,提问作者DarthDonut
相关产品推荐
相关产品推荐

