I am getting crashes for my app. Basically, I have a fragment in which a dialog has to be displayed in one scenario. I had created dialog by extending dialog fragment. The problem is for some users it crashes throwing null pointer exception. This is the snippet of dialog:
VerifyOTPDialog verifyOTPDialog = VerifyOTPDialog.newInstance("Kindly Enter the OTP sent to your Registered Mobile No. :", false, "Verify & Proceed",
"home_screen");
verifyOTPDialog.show(getFragmentManager(), VerifyOTPDialog.class.getSimpleName());
The app crashes at the 2nd line. From crashlytics,I got the following stack trace:
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()' on a null object reference
at android.app.DialogFragment.show(DialogFragment.java:228)
at in.droom.fragments.HomeScreenFragment.updateUI(HomeScreenFragment.java:553)
at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:626)
at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:100)
at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1136)
at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1094)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5637)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
at android.app.DialogFragment.show(DialogFragment.java:228)
at in.droom.fragments.HomeScreenFragment.updateUI(HomeScreenFragment.java:553)
at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:626)
at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:100)
at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1136)
at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1094)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5637)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
As far as I understood, the fragment manager became null at some point of time. But, I am unable to reproduce the scenario. The crashes are happening to no. of users almost everyday.
Update: (VerifyOtpDialog)
public class VerifyOTPDialog extends DialogFragment implements OnClickListener {
private static final String TAG_NAME = VerifyOTPDialog.class.getSimpleName();
private Context ctx;
private Dialog dialog;
private boolean isLaterVisible;
private String strTitle, strBtnTitle, strFragment = "";
private BroadcastReceiver broadcastReceiver;
private ProfileAddressContactInfoModel userModel;
private VerifyOTPDialogDismissed verifyOTPDialogDismissed;
public static final String RECEIVE_OTP = "com.myapp.ACTION_RECEIVED";
private ImageView imgViewForClose;
private RobotoRegularEditTextView editTextForOTP;
private RobotoBoldTextView btnLater, btnVerifyAndProceed;
private RobotoLightTextView txtViewForTitle, txtViewForResendOTP;
public popFragmentListener mPopFragmentListener;
public VerifyOTPDialog() {
}
public static VerifyOTPDialog newInstance(String strTitle, boolean isLaterVisible, String strBtnTitle, String strFragment) {
VerifyOTPDialog dialog = new VerifyOTPDialog();
Bundle b = new Bundle();
b.putString("title", strTitle);
b.putBoolean("isLaterVisible", isLaterVisible);
b.putString("btnTitle", strBtnTitle);
b.putString("strFrom", strFragment);
dialog.setArguments(b);
return dialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = getActivity();
registerReceiver();
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialog = super.onCreateDialog(savedInstanceState);
dialog.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(android.content.DialogInterface dialog, int keyCode, android.view.KeyEvent event) {
if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) {
AppUtil.hideKeyboard();
return true;
} else
return false;
}
});
return dialog;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.verify_otp_popup, container, false);
Bundle b = getArguments();
strTitle = b.getString("title");
isLaterVisible = b.getBoolean("isLaterVisible");
strBtnTitle = b.getString("btnTitle");
strFragment = b.getString("strFrom");
getDialog().setCanceledOnTouchOutside(false);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(0));
userModel = AppUtil.getUserProfile();
imgViewForClose = (ImageView) view.findViewById(R.id.imgViewForClose);
editTextForOTP = (RobotoRegularEditTextView) view.findViewById(R.id.editTextForOTP);
btnLater = (RobotoBoldTextView) view.findViewById(R.id.btnLater);
btnVerifyAndProceed = (RobotoBoldTextView) view.findViewById(R.id.btnVerifyAndProceed);
txtViewForTitle = (RobotoLightTextView) view.findViewById(R.id.txtViewForTitle);
txtViewForResendOTP = (RobotoLightTextView) view.findViewById(R.id.txtViewForResendOTP);
if (userModel != null)
txtViewForTitle.setText(strTitle + " +91 " + userModel.getContactInfo().getMobilePhone());
txtViewForResendOTP.setText(getUnderlinedContent());
if (!isLaterVisible)
btnLater.setVisibility(View.GONE);
btnVerifyAndProceed.setText(strBtnTitle);
imgViewForClose.setOnClickListener(this);
txtViewForResendOTP.setOnClickListener(this);
btnLater.setOnClickListener(this);
btnVerifyAndProceed.setOnClickListener(this);
return view;
}
public interface VerifyOTPDialogDismissed {
void dialogDismissing(String... s);
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
}
public VerifyOTPDialogDismissed getDialogDismissListener() {
return verifyOTPDialogDismissed;
}
public void setDialogDismissListener(VerifyOTPDialogDismissed VerifyOTPDialogDismissed) {
this.verifyOTPDialogDismissed = VerifyOTPDialogDismissed;
}
private void registerReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(RECEIVE_OTP);
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String strOTP = intent.getExtras().getString("otp");
if (strOTP != null && editTextForOTP != null)
editTextForOTP.setText(strOTP);
}
};
ctx.registerReceiver(broadcastReceiver, intentFilter);
}
private SpannableString getUnderlinedContent() {
SpannableString content = new SpannableString(getResources().getString(R.string.resend_otp));
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
content.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.blue_button)), 0, content.length(), 0);
return content;
}
private void sendOTP(HashMap<String, String> params) {
Response.Listener<JSONObject> responseListener = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
Logger.debugMessage("Response Object", response.toString());
String responseCode = response.getString("code");
if (responseCode.equalsIgnoreCase("success")) {
String message = response.getString("message");
Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show();
} else if (responseCode.equalsIgnoreCase("failed")) {
if (response.has("error")) {
if (response.has("error_code")) {
String error_code = response.optString("error_code");
displayMessageAlert(response.optString("error"), "", error_code);
} else {
displayMessageAlert(response.optString("error"), "", "");
}
} else if (response.has("errors")) {
JSONArray errorsArray;
try {
errorsArray = response.getJSONArray("errors");
Toast.makeText(ctx, errorsArray.getString(0), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
};
Api.sendOTP(params, responseListener, errorListener);
}
private void verifyOTP(HashMap<String, String> params, final String strFragment) {
Response.Listener<JSONObject> responseListener = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
Logger.debugMessage("Response Object", response.toString());
String responseCode = response.getString("code");
if (responseCode.equalsIgnoreCase("success")) {
if (userModel != null) {
userModel.setPhoneVerified(true);
userModel.setOTPVerified(true);
AppUtil.saveUserProfile(userModel);
}
VerifyOTPDialog.this.dismissAllowingStateLoss();
String event_name = "";
if (strFragment.equalsIgnoreCase("SellFragment")) {
event_name = "otp_verified_on_sell";
MainActivity.getInstance().pushFragment(SellFragment.newInstance(), SellFragment.class.getSimpleName(), true);
} else if (strFragment.equalsIgnoreCase("QuickSellFragment")) {
event_name = "otp_verified_on_quick_sell";
MainActivity.getInstance().pushFragment(new QuickSellFragment(), QuickSellFragment.class.getSimpleName(), true);
} else if (strFragment.equalsIgnoreCase("gotoPaymentFlow")) {
event_name = "otp_verified_on_payment";
DraftSummaryFragment.getInstance().gotoPaymentFlow();
} else if (strFragment.equalsIgnoreCase("gotoPlaceBidPage")) {
event_name = "otp_verified_on_place_bid";
verifyOTPDialogDismissed.dialogDismissing(strFragment);
} else if (strFragment.equalsIgnoreCase("make_best_offer")) {
event_name = "otp_verified_on_make_best_offer";
verifyOTPDialogDismissed.dialogDismissing(strFragment);
} else if (strFragment.equalsIgnoreCase("checkAvailableFees")) {
event_name = "otp_verified_on_quick_sell";
QuickSellDraftSummaryFragment.getInstance().checkAvailableFees();
} else if (strFragment.equalsIgnoreCase("home_screen")) {
event_name = "otp_verified_for_casual_seller";
} else if (strFragment.equalsIgnoreCase("my_profile")) {
event_name = "otp_verified_from_my_profile";
} else if (strFragment.equalsIgnoreCase("my_profile")) {
event_name = "otp_verified_from_my_profile";
} else if (strFragment.equalsIgnoreCase("pro_seller_profile_settings")) {
event_name = "otp_verified_from_pro_seller_profile_settings";
} else if (strFragment.equalsIgnoreCase("pro_seller_welcome")) {
event_name = "otp_verified_from_pro_seller_welcome";
} else if (strFragment.equalsIgnoreCase("seller_badges")) {
event_name = "otp_verified_from_seller_badges";
} else if (strFragment.equalsIgnoreCase("trust_factor")) {
event_name = "otp_verified_from_trust_factor";
} else if (strFragment.equalsIgnoreCase("ProSellerDashboard"))
MainActivity.getInstance().pushFragment(ProSellerDashboardFragment.newInstance(false), ProSellerDashboardFragment.class.getSimpleName(), true);
else
event_name = "otp_verified_from_my_account";
JSONObject post = BetaOutAPIs.getPostDataForUserAdd(userModel, "update");
JSONArray eventArray = new JSONArray();
JSONObject event = new JSONObject();
event.put("name", event_name);
event.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
eventArray.put(event);
post.put("events", eventArray);
BetaOutAPIs.sendEventToBetaOut(post, TAG_NAME);
BaseApplication.getInstance().trackMoEngageEvents(event_name, new PayloadBuilder().build());
} else if (responseCode.equalsIgnoreCase("failed")) {
btnVerifyAndProceed.setEnabled(true);
if (response.has("error")) {
if (response.has("error_code")) {
String error_code = response.optString("error_code");
displayMessageAlert(response.optString("error"), "", error_code);
} else {
displayMessageAlert(response.optString("error"), "", "");
}
} else if (response.has("errors")) {
Toast.makeText(ctx, response.optString("errors"), Toast.LENGTH_SHORT).show();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
Api.verifyOTP(params, responseListener, errorListener);
}
private boolean validateOTP() {
String validationMessage = "";
boolean isValid = true;
String email = editTextForOTP.getText().toString();
if (email.length() == 0) {
isValid = false;
validationMessage = "Please Enter OTP";
Toast.makeText(getActivity(), validationMessage, Toast.LENGTH_SHORT).show();
}
return isValid;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imgViewForClose:
VerifyOTPDialog.this.dismissAllowingStateLoss();
break;
case R.id.txtViewForResendOTP:
if (userModel != null) {
HashMap<String, String> params = new HashMap<String, String>();
params.put("user_id", AppSharedPref.getUserId());
params.put("phone", userModel.getContactInfo().getMobilePhone());
sendOTP(params);
}
break;
case R.id.btnLater:
VerifyOTPDialog.this.dismissAllowingStateLoss();
if (mPopFragmentListener != null)
mPopFragmentListener.gotoRootFragment();
if (strFragment.equalsIgnoreCase("SellFragment")) {
MainActivity.getInstance().pushFragment(SellFragment.newInstance(), SellFragment.class.getSimpleName(), true);
} else if (strFragment.equalsIgnoreCase("QuickSellFragment")) {
MainActivity.getInstance().pushFragment(new QuickSellFragment(), QuickSellFragment.class.getSimpleName(), true);
} else if (strFragment.equalsIgnoreCase("gotoPlaceBidPage")) {
//verifyOTPDialogDismissed.dialogDismissing();
} else if (strFragment.equalsIgnoreCase("ProSellerDashboard"))
MainActivity.getInstance().pushFragment(ProSellerDashboardFragment.newInstance(false), ProSellerDashboardFragment.class.getSimpleName(), true);
break;
case R.id.btnVerifyAndProceed:
if (validateOTP()) {
btnVerifyAndProceed.setEnabled(false);
HashMap<String, String> map = new HashMap<String, String>();
map.put("user_id", SharedPref.getUserId());
map.put("code", editTextForOTP.getText().toString());
verifyOTP(map, strFragment);
}
break;
default:
break;
}
}
protected void displayMessageAlert(String message, String title, final String error_code) {
String s = "Alert";
if (title != null && title.length() > 0) {
s = title;
}
if (message != null) {
new AlertDialog.Builder(ctx).setTitle(s).setMessage(message)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (error_code.toLowerCase().equals("logout")) {
AppUtil.logoutUser((MainActivity) ctx);
MainActivity.getInstance().pushFragment(LoginFragment.newInstance(true, true), LoginFragment.class.getSimpleName(), true);
}
dialog.dismiss();
}
}).show();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (broadcastReceiver != null) {
ctx.unregisterReceiver(broadcastReceiver);
}
}
public void setPopFragmentListener(popFragmentListener mPopFragmentListener) {
this.mPopFragmentListener = mPopFragmentListener;
}
public interface popFragmentListener {
void gotoRootFragment();
}
}
You should get the fragment manager before :
FragmentManager fragMan = getSupportFragmentManager();
then test it's nullity
if(fragMan != null){
// Do stuff
}
And if you are using if in DoInBackground of the asynctask you should get the Uithread :
runOnUiThread(new Runnable() {
public void run() {
// do stuff on the ui like display fragments
}
});
EDIT :
You should use the support v4 library for supporting fragment
If you are showing from Fragment, then use getChildFragmentManager()
:
Like :
verifyOTPDialog.show(getChildFragmentManager(),VerifyOTPDialog.class.getSimpleName());
You said you are using android.app.fragment
to host your fragment. Since you are making the dialog using android DialogFragment, the dialog Fragment itself is a fragment, thus making this a case of nested Fragments in android. When we nest frgaments we use getChildFragmentManager().
The Support for nested fragments in android was not available in API 11. The support for nested Fragments started from API 17 and onwards. If you want to use nested Fragments in API 11 - 16, then you have to use the support library fragments.
So you have to make your DialogFragment of type android.support.v4.app.dialogFragment
and your fragment of type android.support.v4.app.fragment
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With