在第一个应用启动时,当用户想通过点击按钮开始操作时,我的应用会请求一些权限。在用户授予权限后,应该替换我的MainActivity中的Fragment。
我的SecondFragment上的所有内容都被调用(onCreate(), onStart(), onResume(),...
),但它不会显示出来。
在第二个应用程序启动时,当不需要再次请求权限时,一切正常并显示SecondFragment。
两种方式都使用相同的代码:
/**
* This method starts the second fragment.
*/
private void startSecondView(){
final SecondFragment frag = new SecondFragment();
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, frag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
我的片段放在FrameLayout中。
更新 我很快尝试构建一个虚拟应用程序来重现此错误。 不完全相同的行为,但在请求权限后替换Fragment时虚拟应用程序崩溃。在第二个应用程序开始everthing工作正常。
这是一些代码。
activity_main.xml中
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<!-- The main content view -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MergeRootFrame"/>
</RelativeLayout>
<!-- The navigation drawer -->
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/navigation_menu">
<android.support.design.widget.NavigationView
android:id="@+id/navigation_drawer_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:elevation="0dp"
app:menu="@menu/menu_navigation_dawer_bottom"/>
</android.support.design.widget.NavigationView>
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume(){
super.onResume();
final FirstFragment frag = new FirstFragment();
frag.setRetainInstance(true);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, frag)
.commit();
}
}
FirstFragment
public class FirstFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private static final int PERMISSIONS_REQUEST = 12;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public FirstFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FirstFragment.
*/
// TODO: Rename and change types and number of parameters
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
Button button = (Button) rootView.findViewById(R.id.btnStartTour);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkRequirementsAndStart();
}
});
// Inflate the layout for this fragment
return rootView;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onDetach() {
super.onDetach();
}
private void checkRequirementsAndStart(){
final String[] checkPermissions = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.SEND_SMS,
Manifest.permission.CALL_PHONE
};
if(hasPermissions(getActivity(), checkPermissions)) {
startSecondView();
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
requestPermissions(checkPermissions, PERMISSIONS_REQUEST);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST) {
for(int x = 0; x < permissions.length; x++){
if(grantResults[x] != PackageManager.PERMISSION_GRANTED){
return; //Abort if permission is missing
}
}
startSecondView();
}
}
private void startSecondView(){
final SecondFragment frag = new SecondFragment();
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, frag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
public boolean hasPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
}
SecondFragment
public class SecondFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public SecondFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SecondFragment.
*/
// TODO: Rename and change types and number of parameters
public static SecondFragment newInstance(String param1, String param2) {
SecondFragment fragment = new SecondFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public void onDetach() {
super.onDetach();
}
}
更新
虚拟应用程序错误:
致命的例外:主要 处理:com.example.permissiontest,PID:15228 java.lang.RuntimeException:传递结果失败ResultInfo {who = @ android:requestPermissions:,request = 12, result = -1,data = Intent { act = android.content.pm.action.REQUEST_PERMISSIONS(有额外的)}}到 活动 {com.example.permissiontest / com.example.permissiontest.MainActivity}: java.lang.IllegalStateException:之后无法执行此操作 的onSaveInstanceState 在android.app.ActivityThread.deliverResults(ActivityThread.java:3699) 在android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) 在android.app.ActivityThread.-wrap16(ActivityThread.java) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1393) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:148) 在android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 引起:java.lang.IllegalStateException:在onSaveInstanceState之后无法执行此操作 在android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1842) 在android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1860) 在android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:650) 在android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:609) 在com.example.permissiontest.MainActivity.startSecondView(MainActivity.java:75) 在com.example.permissiontest.MainActivity.onRequestPermissionsResult(MainActivity.java:40) 在android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6582) 在android.app.Activity.dispatchActivityResult(Activity.java:6460) 在android.app.ActivityThread.deliverResults(ActivityThread.java:3695) 在android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) 在android.app.ActivityThread.-wrap16(ActivityThread.java) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1393) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:148) 在android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)