Starting method from class causes Null Pointer Exception - android

I am trying to access/call a method I have in my Activity from my class but I am getting null pointer exception when doing so.
Here's the method i am trying to call. This method is in my Activity:
public void start(Context context){
mHelper = new IabHelper(context.getApplicationContext(), base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " + result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
mHelper.enableDebugLogging(true, TAG);
startPurchase();
}
}
});
}
In my class where I am calling it from, I have made an instance of the class:
ThemeActivity themeact = new ThemeActivity();
And I am trying to call it from an onClicklistener within my class:
new AlertDialog.Builder(getContext())
.setMessage(
"Would you like to purchase this theme?")
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface dialog, int id) {
//Here is where I am calling it
themeact.start(getContext());
}
}).setNegativeButton("No", null).show();
And I receive the following error in LogCat:
FATAL EXCEPTION: main
java.lang.NullPointerException
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109)
at test.test.util.IabHelper.<init>(IabHelper.java:164)
at test.test.ThemeActivity.start(ThemeActivity.java:161)
at test.test.ColorCard$1$1.onClick(ColorCard.java:67)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:171)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5225)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
EDIT
I realized that I was calling the wrong method to start with, and now i am calling the correct method and it still crashes with a null pointer exception with a different error. I have tried to pass a context and it still isn't working. Whenever I try to call the method start(); from the on create of my Activity, it works. But then when trying to call the exact same method from my other class it crashes and I have no idea why. I initialize everything from within the method itself so I'm not sure why it crashes with null.

Try passing the context variable of the activity as an argument to startPurchase() method

In the end I fixed my problem by moving my class inside my activity class. I am not sure why it works now but it didn't when I had the class I was using as a separate class.

Related

unable to start activity from onPostexecute() using interface

I need to start another activity from the onPosExecute method of the AsyncTask. The AsyncTask is a seperate class and not in any activity class.
I have used an interface to do so. The codes are:
This is the onPostExecute() method
#Override
protected void onPostExecute(String json) {
Log.v("JSON", json);
Log.v("updateUI",""+updateUI);
updateUI.changeActivity();
}
This is the interface
public interface UpdateUIListener {
public void changeActivity();
}
And this is the part of the activity class where the interface is implemented
#Override
public void changeActivity() {
Intent blah=new Intent(this,SplashActivity.class);
startActivity(blah);
finish();
}
When I run the code, a null pointer exception shows up, at the line
Intent blah=new Intent(this,SplashActivity.class);
My stacktrace is:
java.lang.NullPointerException
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:135)
at android.content.ComponentName.<init>(ComponentName.java:75)
at android.content.Intent.<init>(Intent.java:3546)
at com.autofoyer.SignUpActivity.changeActivity(SignUpActivity.java:79)
at com.autofoyer.common.MyClientTask.onPostExecute(MyClientTask.java:73)
at com.autofoyer.common.MyClientTask.onPostExecute(MyClientTask.java:23)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5099)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:803)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:570)
at dalvik.system.NativeStart.main(Native Method)
I need to know what is causing and How to solve the null point exception. I need to start and activity from the onPostExecute method. Thanks in advance!
You probably instantiate updateUI with new SplashActivity() or similar. You can't do that. Instead you have to pass a Context into your AsyncTask and use that to call startActivity() . You probably start the AsyncTask from some Activity, so just pass that Activity as a Context when instantiating the AsyncTask.

Android listener serialization

I have CustomDialog class that extends DialogFragment. I override onCreateDialog method, to get custom dialog i wanted.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialog = new Dialog(activity, styleId);
view = activity.getLayoutInflater().inflate(layoutId, null);
dialog.setContentView(view);
if (listener != null) {
listener.onViewInit(view, this);
}
return dialog;
}
This is custom dialog creation code. After view is inflated, I call listener method listener.onViewInit(view, this) of type OnViewInitListener which is interface and extends Serializable, to bind custom code to view (view texts, listeners and etc.) , so that on rotation i want lose my button press logic.
#Override
public void onSaveInstanceState(Bundle bundle) {
bundle.putInt("layoutId", layoutId);
bundle.putInt("styleId", styleId);
bundle.putSerializable("listener", listener);
super.onSaveInstanceState(bundle);
}
public RsCustomDialog setOnListenerAssignment(OnViewInitListener listener) {
this.listener = listener;
return this;
}
When I implement OnViewInitListener from Activity, on orientation change things work as expected:
onCreateDialog is called every time fragment is recreated, and ther are no parcel errors, but when I press applications history button (on rightmost)
(source: cbsistatic.com)
I get this error:
10-09 11:09:38.256: E/AndroidRuntime(24153): FATAL EXCEPTION: main
10-09 11:09:38.256: E/AndroidRuntime(24153): java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = base.RsCustomDialog$OnClickListener)
10-09 11:09:38.256: E/AndroidRuntime(24153): at android.os.Parcel.writeSerializable(Parcel.java:1279)
10-09 11:09:38.256: E/AndroidRuntime(24153): at android.os.Parcel.writeValue(Parcel.java:1233)
10-09 11:09:38.256: E/AndroidRuntime(24153): at android.os.Parcel.writeMapInternal(Parcel.java:591)
10-09 11:09:38.256: E/AndroidRuntime(24153): at android.os.Bundle.writeToParcel(Bundle.java:1627)
10-09 11:09:38.256: E/AndroidRuntime(24153): at android.os.Parcel.writeBundle(Parcel.java:605)
10-09 11:09:38.256: E/AndroidRuntime(24153): at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:133)
I guess this is because, when I implement OnViewInitListener from my activity, java implicitly puts activity variable in implemented object, and Parcel can't handle Activity parcelation.
Can anyone suggest how to deal with this problem, or advice a better solution.
You can't serialize and restore a listener.
Serialization (including using Parcelable) saves the state of an object instance and deserialization puts that state into a new object instance.
Listeners don't have state - which is why your Parcelable implementation isn't saving or restoring anything. The listener variable is a reference to an object instance (one that is known to implement the listener's interface). If a new instance of that object is created (ex: due to rotation, or process being killed due to low memory), it doesn't help for the dialog to attempt restoring the pointer to the previous instance. The previous instance no longer exists and the newly created (correct) instance didn't exist at the time onSaveInstanceState was invoked.
Two possible alternatives:
If the listener is intended to be the Activity which the dialog is attached to, then that can be restored in the DialogFragment's onAttach method
If not, then the Activity can set the Fragment listener when it is created (or re-created). To get a reference to an automatically restored Fragment instance, one can use getFragmentManager().findFragmentById(id) or getFragmentManager().findFragmentByTag(tag)
Your OnViewInitListener should be static and serializable and has all the serializable fields inside. If you reference Activity from it then you do it wrong. To overcome the issue you may:
Reference the activity instance stored in static WeakReference variable which is populated when activity gets created.
Use broadcast receivers
Reregister listener when fragment gets restored with the new one and proper context.
you can write something in onResume and onStop what you listener unregister in onStop method ,register in onResume method
Well, I solved it! What I did is I implemented Parcable as follows:
public abstract class OnClickListener implements DialogInterface.OnClickListener, Parcelable {
#Override
public abstract void onClick(DialogInterface dialog, int which);
#Override
public void writeToParcel(Parcel dest, int flags) {
}
#Override
public int describeContents() {
return 0;
}
}
So my ConfirmDialog code stays the same:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(title).setMessage(text)
.setPositiveButton(R.string.yes, onYes)
.setNegativeButton(R.string.no, onNo).create();
}
#Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putParcelable("onYes", onYes);
bundle.putParcelable("onNo", onNo);
}
The only limitation is do not use auto variables that are not Parcelable in onClick method.
Here is my example of showing this dialog:
showConfirmDialog(getString(R.string.sure_want_to_exit), new base.dialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((NewProtocol) getCurrentActivity()).exit = true;
getCurrentActivity().finish();
}
}, null);
getCurrentActivity() is static method that returns current active activity.

null pointer exception calling a method

I have 2 activities in my app, in the second one I have the code to run when the "about" android action bar icon is clicked. In the first activity I have the same action bar menu items and I want to call this "about" method again, however when I click that, I have null Pointer exception. Anyone help ?
this is the method defined in the second activity - JokeDetailsActivity
public void aboutMe(){
AlertDialog.Builder dialog = new AlertDialog.Builder(JokeDetailsActivity.this);
dialog.setTitle("About");
dialog.setMessage("Hello! I'm ..., the creator of this application."
+"If there is any bug found please freely e-mail me. "+
"\n ...."
);
dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
when I call it in the first activity
case R.id.action_about:
JokeDetailsActivity jd = new JokeDetailsActivity();
jd.aboutMe();
return true;
}
thats the error I'm getting
09-12 20:11:42.748: E/AndroidRuntime(1032): FATAL EXCEPTION: main
09-12 20:11:42.748: E/AndroidRuntime(1032): java.lang.NullPointerException
09-12 20:11:42.748: E/AndroidRuntime(1032): at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:140)
09-12 20:11:42.748: E/AndroidRuntime(1032): at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:103)
09-12 20:11:42.748: E/AndroidRuntime(1032): at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:143)
09-12 20:11:42.748: E/AndroidRuntime(1032): at android.app.AlertDialog$Builder.<init>(AlertDialog.java:360)
09-12 20:11:42.748: E/AndroidRuntime(1032): at ie.myjokes.JokeDetailsActivity.aboutMe(JokeDetailsActivity.java:293)
09-12 20:11:42.748: E/AndroidRuntime(1032): at ie.myjokes.CategoryActivity.onOptionsItemSelected(CategoryActivity.java:140)
09-12 20:11:42.748: E/AndroidRuntime(1032): at android.app.Activity.onMenuItemSelected(Activity.java:2548)
No, don't do this
JokeDetailsActivity jd = new JokeDetailsActivity();
You are getting the error in the following line because you don't have the correct Context.
AlertDialog.Builder dialog = new AlertDialog.Builder(JokeDetailsActivity.this);
You are trying to call it in one Activity but use the Context of another Activity
You have a few options
1 Simply recreate this function in your other Activity and just
call it in that Activity with the proper Context (ActivityName.this)
2 Create a separate class that all of these Activities can call to use this function and pass the proper Context to that class.
3 Put this method in a BaseActivity and have your Activities extend this BaseActivity and place the method there.
I remembered #4
You could also create a separate Activity, like AboutActivity, to handle/show whatever you want and give it a Dialog Theme by adding the following line to the <activity tag in your manifest
android:theme="#android:style/Theme.Dialog"
then you just start that Activity from wherever you need.
What is this
JokeDetailsActivity jd = new JokeDetailsActivity();
jd.aboutMe();
If you want to start Activity you should do this using intent
You should never instantiate Activities
Create a seperate Class pass Context and create your aboutMe() method there and then reuse it
OR
Alternatively you can create it as static method in it
public static void aboutMe(Context mContext){
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle("About");
dialog.setMessage("Hello! I'm ..., the creator of this application."
+"If there is any bug found please freely e-mail me. "+
"\n ...."
);
dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
then use it like
JokeDetailsActivity.aboutMe(getApplicationContext());
Yea that's it you start an Activity like:
Intent intent = new Intent(this, YourActivity.class);
startActivity(intent);
You cannot instantiate an Activity class like that and use it. The Activity creation is handled by Android system and it will need to get things like Context and stuff (which is the thing that you dont have, and you do use when you, for example, instantiate the AltertDialog builder, hence the null pointer exception). I would suggest that you make that method aboutMe a static method, and pass in a Context object to it:
public static void aboutMe(Context context){
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle("About");
dialog.setMessage("Hello! I'm ..., the creator of this application."
+"If there is any bug found please freely e-mail me. "+
"\n ...."
);
dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
Declare that method as static and call it as JokeDetailsActivity.aboutMe(yourActivityContext). Don't create an object of activity and remember to pass the context, which you can then use to create the dialog. #Hi-Tech KitKat Android has givn more detailed answer.

getTargetFragment() returns null -- works in one place but not another

I am having an odd problem. I am implementing the same code in two places (both in ListFragments), but one works and the other throws a NullPointerException.
Here's my code (all part of a subclass of ListFragment):
public static class DeleteDialogFragment extends DialogFragment {
static DeleteDialogFragment newInstance(int arg) {
return new DeleteDialogFragment();
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.confirm_delete)
.setMessage(R.string.teacher_confirm_delete_message)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((TeachersFragment)getTargetFragment()).deleteTeacher();
}
})
.setNegativeButton(R.string.no, null)
.create();
}
}
public void deleteTeacher() {
DbUtils.deleteTeacher(context, selectedItem);
}
I have exactly the same thing in another ListFragment (except I'm casting it to an AssignmentListFragment instead of a TeachersFragment), and that one works flawlessly. In both cases the DeleteDialogFragment class is nested directly under the ListFragment.
The error message I'm getting is as follows:
E/AndroidRuntime(15282): FATAL EXCEPTION: main
E/AndroidRuntime(15282): java.lang.NullPointerException
E/AndroidRuntime(15282): at com.acedit.assignamo.setup.TeachersFragment.access$6(TeachersFragment.java:145)
E/AndroidRuntime(15282): at com.acedit.assignamo.setup.TeachersFragment$DeleteDialogFragment$1.onClick(TeachersFragment.java:137)
E/AndroidRuntime(15282): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
E/AndroidRuntime(15282): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(15282): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(15282): at android.app.ActivityThread.main(ActivityThread.java:4575)
E/AndroidRuntime(15282): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(15282): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(15282): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
E/AndroidRuntime(15282): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
E/AndroidRuntime(15282): at dalvik.system.NativeStart.main(Native Method)
Given that getTargetFragment() returns null (I checked in debug mode by assigning the return value to a temporary variable and it is null), it seems odd that it makes it to the deleteTeacher() method before crashing (public void deleteTeacher() { is line 145).
Any ideas what the heck is wrong? If you need more code, just let me know.
EDIT: Here is the code where I call setTargetFragment (in my other instance of this code I was able to use this instead of getTargetFragment, so I think that is where the problem lies.
private class CustomOnClickListener implements OnClickListener {
public void onClick(View v) {
Toast.makeText(context, "Button pressed", Toast.LENGTH_SHORT).show();
if (v == viewHolder.editButton)
startActivity(new Intent(context, getEditClass()).putExtra(Values.KEY_ROWID, (Long)v.getTag()));
else { // Delete it
selectedItem = (Long) v.getTag();
DeleteDialogFragment frag = new DeleteDialogFragment();
frag.setTargetFragment(getTargetFragment(), 0);
frag.show(getFragmentManager(), "confirmDelete");
}
}
}
The problem is you don't have a reference to the TeacherFragment since getTargetFragment() is null, but you can fetch the Fragment other ways try using the FragmentManager's getFragmentById() or getFragmentByTag() methods.

DialogFragment : NullPointerException (support library)

I'm using the excellent ACRA library to receive error reports from my apps.
I'm receiving a lot of reports from customers concerning an NPE in DialogFragment, but Im unable to reproduce it :
java.lang.NullPointerException
at android.support.v4.app.DialogFragment.onActivityCreated(SourceFile:366)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:892)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1083)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1065)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(SourceFile:1844)
at android.support.v4.app.FragmentActivity.onStart(SourceFile:519)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1133)
at android.app.Activity.performStart(Activity.java:4475)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1929)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
The NPE happens inside the support library (#line 366):
353 #Override
354 public void onActivityCreated(Bundle savedInstanceState) {
(...)
361 View view = getView();
362 if (view != null) {
363 if (view.getParent() != null) {
364 throw new IllegalStateException("DialogFragment can not be attached to a container view");
365 }
366 mDialog.setContentView(view);
367 }
Im unable to reproduce the problem on any of my device (from 2.2 to 4.1.1). Since there's no reference to any of my code, is it a library bug?
I have had to debug the same issue in a project.
Typically Dialog fragment is used as below
#Override
public Dialog onCreateDialog (Bundle savedInstanceState)
{
//Create custom dialog
return dialog;
}
Try updating it to the following
#Override
public Dialog onCreateDialog (Bundle savedInstanceState)
{
//Create custom dialog
if (dialog == null)
super.setShowsDialog (false);
return dialog;
}
This will prevent DialogFragment.onAtivityCreated() from executing methods on the null member variable mDialog.
This is a relatively common crash that I've seen reported within StackOverflow, and it's due to the dialog not being created properly, causing mDialog to be null. The brute force method I initially used to prevent the crash:
#Override
public void onActivityCreated(Bundle arg0) {
if (getDialog() == null ) { // Returns mDialog
// Tells DialogFragment to not use the fragment as a dialog, and so won't try to use mDialog
setShowsDialog( false );
}
super.onActivityCreated(arg0); // Will now complete and not crash
}
While the above is probably better than a crash, this doesn't address the root cause of why the dialog failed to be created. There could be many reasons for that and that's what needs to be debugged.
In my situation, I found that I needed to implement DialogFragment's onCreateDialog() instead of onCreateView() to properly create the dialog 100% of the time. (onCreateView() almost always works to create the dialog, but I PROVED that there are reproducible corner cases where onCreateView() fails to work, causing mDialog to become null. On the other hand, I always found that onCreateDialog() properly created DialogFragment's dialog.)
DialogFragment.mDialog can be null if DialogFragment.dismiss() is called before onActivityCreated() is called.
I had the NPE.
But surrounding the super.OnActivityCreated with a try/catch did not help.
What did help was the removal of a static field that was left over from copying an example.
So, no static fields inside an overridden DialogFragment.
No it's not. This is the common error if the SetContentView crashes. setContentView calls the constructors of the Controls of your view. One throwed a nullPointerException.
If you are overriding onCreateView(..) to instantiate the view of your DialogFragment you need to show it using a fragment transaction and put setShowsDialog to false to avoid this error. i.e:
//Instantiate your DialogFragment and fragmentManager previously and then just do this:
dialogFragment.setShowsDialog(false);
FragmentTransaction fT = fragmentManager.beginTransaction();
fT.add(0, dialogFragment, TAG);
fT.commit();

Categories

Resources