Attempt to invoke virtual method on a null object reference - Android - java

I get a crash report from my production app sometimes, the line below I think is the source of the problem:
Attempt to invoke virtual method 'java.util.ArrayList
foto.studio.SQLiteDataSource.getAllImageItems()' on a null object
reference at
foto.studio.MainActivity.onCreateOptionsMenu(MainActivity.java:267)
the method it is pointing to inside MainActivity (and the responsible line highlighted with "==>" ):
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
final Menu m = menu;
final MenuItem item = menu.findItem(R.id.action_notifications);
View actionView = item.getActionView();
notifTextView = (TextView) actionView.findViewById(R.id.notifTextView);
ArrayList <ImageItemsSetter> pendingOrdersList = new ArrayList<ImageItemsSetter>();
===> pendingOrdersList = datasource.getAllImageItems(); <===
Log.i("value", "String calue of pendingorderlist: " + String.valueOf(pendingOrdersList.size()));
String unreadNotifs = String.valueOf(pendingOrdersList.size());
if (!unreadNotifs.equals("0")) {
notifTextView.setText(unreadNotifs);
} else {
notifTextView.setVisibility(View.GONE);
}
item.getActionView().setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
m.performIdentifierAction(item.getItemId(), 0);
}
});
return true;
}
And the method from SQLiteDataSource:
public ArrayList<ImageItemsSetter> getAllImageItems() {
Cursor cursor = database.query(SQLiteHelper.TABLE_IMAGES,
allColumnsImages, null, null, "product", null, null);
//Log.i("LOGTAG", "Returned " + cursor.getCount() + " rows");
ArrayList<ImageItemsSetter> products = cursorToListImages(cursor);
return products;
}
What could be wrong? My ArrayList (pendingOrdersList) is initiated right before I use it, why does it say that it is null??
Line where I initialize the database:
#Override
protected void onResume() {
super.onResume();
initImageLoader();
datasource = new SQLiteDataSource(this);
datasource.open();
invalidateOptionsMenu();
// facebook analytics
AppEventsLogger.activateApp(this);
//get or update appVersion string
getAppVersion();
}
Full Report:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{foto.studio/foto.studio.MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method
'java.util.ArrayList foto.studio.SQLiteDataSource.getAllImageItems()'
on a null object reference at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2693)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2758)
at android.app.ActivityThread.access$900(ActivityThread.java:177) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102) at
android.os.Looper.loop(Looper.java:145) at
android.app.ActivityThread.main(ActivityThread.java:5942) at
java.lang.reflect.Method.invoke(Native Method) at
java.lang.reflect.Method.invoke(Method.java:372) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'java.util.ArrayList
foto.studio.SQLiteDataSource.getAllImageItems()' on a null object
reference at
foto.studio.MainActivity.onCreateOptionsMenu(MainActivity.java:267) at
android.app.Activity.onCreatePanelMenu(Activity.java:2947) at
com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:606)
at
com.android.internal.policy.impl.PhoneWindow.doInvalidatePanelMenu(PhoneWindow.java:980)
at
com.android.internal.policy.impl.PhoneWindow$1.run(PhoneWindow.java:308)
at
com.android.internal.policy.impl.PhoneWindow.doPendingInvalidatePanelMenu(PhoneWindow.java:954)
at
com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2194)
at android.app.Activity.onRestoreInstanceState(Activity.java:1092) at
android.app.Activity.performRestoreInstanceState(Activity.java:1037)
at
android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1175)
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
... 10 more

Be careful when you use custom code in onCreateOptionsMenu() : this method may be called at any time after onCreate(), depending on the Android version and other factors. Your data source is obviously not yet ready when the method is called, so you must handle that case too.
I may suggest that you test if the data source is null before initializing the menu items, and as soon as your data source is ready, initialize the items if it was not yet done.

Related

Application crashing when user signs out [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed last year.
Guys i have been making this simple Uber app and whenever the Driver LogsOut my app crashes because the getCurrentUser() method is returning a null value. But whenever the user logsOut im closing the activity, and before calling getCurrentUser() i have this if(getApplicationContext()!=null) which should return false because the activity is closed so it should prevent getCurrentUser() from being called. How do i prevent it from crashing? What am i missing here?
This is where on Button click i logOut my user
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//some code here
mLogout=(Button)findViewById(R.id.logout);
mLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
isLoggingOut = true;
disconnectDriver();
//Signing out user here
FirebaseAuth.getInstance().signOut();
Intent intent = new Intent(DriverMapActivity.this, MainActivity.class);
startActivity(intent);
return;
}
});
//some code here
}
This is where the error is happening
#Override
//this is going to run whenever the driver location changes
public void onLocationChanged(Location location) {
if(getApplicationContext()!=null) {
mLastLocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//
//This is where the error is happening
//java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference refAvailable = FirebaseDatabase.getInstance().getReference("driversAvailable");
DatabaseReference refWorking = FirebaseDatabase.getInstance().getReference("driversWorking");
GeoFire geoFireAvailable = new GeoFire(refAvailable);
GeoFire geoFireWorking = new GeoFire(refWorking);
switch(customerId){
case "":
geoFireWorking.removeLocation(userId);
geoFireAvailable.setLocation(userId, new GeoLocation(location.getLatitude(), location.getLongitude()));
break;
default:
geoFireAvailable.removeLocation(userId);
geoFireWorking.setLocation(userId, new GeoLocation(location.getLatitude(), location.getLongitude()));
break;
}
}
}
This is the Error Log
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.jonanako.uber, PID: 15522
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
at com.jonanako.uber.DriverMapActivity.onLocationChanged(DriverMapActivity.java:211)
at com.google.android.gms.internal.location.zzat.notifyListener(com.google.android.gms:play-services-location##18.0.0:2)
at com.google.android.gms.common.api.internal.ListenerHolder.zaa(com.google.android.gms:play-services-base##18.0.1:2)
at com.google.android.gms.common.api.internal.zacb.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Since you assign false to your isLoggingOut = true; whenever you click on the button, you should just check if(getApplicationContext()!=null && !isLoggingOut) so the code wont run whenever isLoggingOut==false;
getApplicationContext() won't be null when you finish() Activity, even last or one and only. consider using if(!isFinishing()), lifecycle checking or just set own boolean flag.
additionally you may (should) also check that getCurrentUser() returns null, that would mean that user logs out. if is null then don't call any method on returned object (because nothing is returned in fact)
if(!isFinishing() && FirebaseAuth.getInstance().getCurrentUser()!=null) {

Set switch statement based on number of clicks

My application is crashing and I believe it is due to the SharedPreferencesManager prefManager = SharedPreferencesManager.getInstance(this); being stored globally in Contentclass. However, if I take it out of there then I cannot use prefManager within the switch statement further down.
I want to use the number of clicks from prefManager to determine my switch statement. How can I get around this?
public class Content extends AppCompatActivity {
Button selectAnotherButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
final SharedPreferencesManager prefManager = SharedPreferencesManager.getInstance(this);
selectAnotherButton = findViewById(R.id.button_select_another);
selectAnotherButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
prefManager.increaseClickCount();
for (int i = 0; i <= 100; i+=2) {
ShowRewardDialog();
}
}
});
private void ShowRewardDialog() {
String message = "";
//show dialog
// set text based on an if statement you need to create
switch (SharedPreferencesManager.getInstance(this).increaseClickCount()){
case 2 :
message = "You are rewarded with a video";
break;
case 4 :
message = "You are rewarded with a the yellow smiley face in the homepage";
break;
case 6 :
message = "You are rewarded with a video";
break;
case 8 :
message = "You are rewarded with a the green smiley face in the homepage";
break;
case 10 :
message = "You are rewarded with a video";
break;
case 12 :
message = "You are rewarded with a the red smiley face in the homepage";
break;
case 14 :
message = "You are rewarded with a video";
break;
default :
message="";
}
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.custom_dialog);
SpannableString title = new SpannableString("YOU GAINED A REWARD");
title.setSpan(new ForegroundColorSpan(context.getResources().getColor(R.color.purple))
, 0, title.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// set the custom dialog components - text, image and button
TextView text = dialog.findViewById(R.id.dialog_text);
dialog.setTitle(title);
text.setText(message);
Button dialogButton = dialog.findViewById(R.id.dialog_button_OK);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
}
Stack Trace:
06-14 21:57:39.420 15488-15488/com.mima.chilltime E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mima.chilltime, PID: 15488
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.mima.chilltime/com.mima.chilltime.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2989)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3260)
at android.app.ActivityThread.access$1000(ActivityThread.java:218)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1734)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6934)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:111)
at com.mima.chilltime.SharedPreferencesManager.<init>(SharedPreferencesManager.java:19)
at com.mima.chilltime.SharedPreferencesManager.getInstance(SharedPreferencesManager.java:25)
at com.mima.chilltime.MainActivity.<init>(MainActivity.java:25)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.Class.newInstance(Class.java:1690)
at android.app.Instrumentation.newActivity(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2979)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3260) 
at android.app.ActivityThread.access$1000(ActivityThread.java:218) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1734) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:145) 
at android.app.ActivityThread.main(ActivityThread.java:6934) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199) 
Try using
SharedPreferencesManager.getInstance(getApplicationContext());
instead of using this
In the SharedPreferencesManager.getInstance(this); .... this refers to the particular activity (i.e. not global) (i.e. its lifecycle directly related to the current context).
On the other hand, if you clearly need a reference to the global state of your application, then you can use ApplicationContext.
From Android Documentation (my emphasis) :
public Context getApplicationContext()
Return the context of the single, global Application object of the
current process. This generally should only be used if you need a
Context whose lifecycle is separate from the current context, that is
tied to the lifetime of the process rather than the current component.
So change to:
SharedPreferencesManager prefManager = SharedPreferencesManager.getInstance(getApplicationContext());

Android Studio Bluetooth :- attempt to invoke a virtual method on a null object reference

I am building a simple app which switches on the Bluetooth of a device and sets it to visible.
I have a separate java class file which has the Bluetooth functions I need, and these are called from another java class which is linked to my activity, through an object of the said class.
This is my code:
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
/**
* Created by mark on 11/11/2016.
*/
public class Bluetooth_API extends AppCompatActivity{
BluetoothAdapter blueAdp;
public Bluetooth_API() {
blueAdp = BluetoothAdapter.getDefaultAdapter();
}
protected int bluetooth_ON() {
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 0);
//blueAdp.enable(); //instead of above line - without alert dialog for permission
return 0;
}
protected int bluetooth_OFF() {
blueAdp.disable(); //
return 0;
}
protected int bluetooth_setVisible() {
if(!blueAdp.isDiscovering()) {
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE), 0);
}
return 0;
}
}
And this is the part of the code from the other activity which is calling my functions:
scanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent nextLayout = new Intent(getApplicationContext(), com.ai.mark.robot_dancing.Scanning_Devices.class);
startActivity(nextLayout);
blue.bluetooth_ON();
//blue.bluetooth_setVisible();
}
});
I am getting the error below once I run my code, I believe it has to do with the activity not being the right one since my Bluetooth functions are in another file (I also tried copying the methods to my activity class and they worked beautifully).
Error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ai.mark.robot_dancing, PID: 21314
java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread
android.app.ActivityThread.getApplicationThread()' on a null object
reference
at android.app.Activity.startActivityForResult(Activity.java:3951)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:77)
at android.app.Activity.startActivityForResult(Activity.java:3912)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
at com.ai.mark.robot_dancing.Bluetooth_API.bluetooth_ON(Bluetooth_API.java:20)
at com.ai.mark.robot_dancing.Bluetooth_Panel$6.onClick(Bluetooth_Panel.java:146)
at android.view.View.performClick(View.java:5210)
at android.view.View$PerformClick.run(View.java:21328)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5551)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Any ideas on what is causing this?
Thanks.
Don't invoke such code in Activity constructor:
blueAdp = BluetoothAdapter.getDefaultAdapter();
Use onCreate(android.os.Bundle) for that:
#Override
protected void onCreate(Bundle savedInstanceState) {
blueAdp = BluetoothAdapter.getDefaultAdapter();
}

Fatal exception while starting activity using intent (null pointer exception)

The following piece of code is throwing a null pointer exception in my application.Im trying to invoke an activity through an intent, (some background info on this is that the activity being opened is triggered through the click of a button, thus I have called the startActivity() function in the button's onclickListener itself.
Here's the code:
public class CategoryButtonOnClickListener extends Activity implements View.OnClickListener {
private final int position;
public CategoriesPage categoriesPage;
Context context;
public CategoryButtonOnClickListener(int position, Context contextPassed) {
this.position = position;
this.context = contextPassed;
categoriesPage = new CategoriesPage();
}
public void onClick(View v) {
callCategoryList(this.position);
}
public void callCategoryList(int position) {
String[] categories = categoriesPage.getCategories();
Intent categoriesList = new Intent(this.context,BooksWithCategories.class);
//I tried commenting this code to fix it as seen from another post, didnt work
//categoriesList.putExtra("Category:",categories[position]);
startActivity(categoriesList);
//Toast.makeText(context,categories[position],Toast.LENGTH_LONG).show();
}
}
The error thrown is as follows:
1-17 23:27:15.076 2614-2614/com.dogra.booker E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.dogra.booker, PID: 2614
java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
at android.app.Activity.startActivityForResult(Activity.java:3736)
at android.app.Activity.startActivityForResult(Activity.java:3697)
at android.app.Activity.startActivity(Activity.java:4007)
at android.app.Activity.startActivity(Activity.java:3975)
at com.dogra.booker.UI.Model.CategoryButtonOnClickListener.callCategoryList(CategoryButtonOnClickListener.java:36)
at com.dogra.booker.UI.Model.CategoryButtonOnClickListener.onClick(CategoryButtonOnClickListener.java:29)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Any suggestions on what could be the problem are appreciated.
Place this method in your code :
Activity getAct() {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
return null;
}
and then use it for starting the activity:
Intent categoriesList = new Intent(getAct(),BooksWithCategories.class);
can try this
Intent categoriesList = new Intent(CategoryButtonOnClickListener.this,BooksWithCategories.class);

Shared Preferences Null Pointer Exception

I am working on adding Shared Preferences to my Note taking Android App and I am running into a peculiar null pointer exception. I am currently testing settings for font size and typeface in my app and have been able to successfully save the shared preferences for both but am having trouble with the retrieval part. When the settings are changed, they successfully change the font and font size on a Fragment for the remainder of time the app is opened but I cannot restore them if the app is restarted.
First weird Null Pointer is in the onCreate.
OnCreate:
//create a new note fragment if one has not been created yet
mNoteFragment = (NoteFragment) getFragmentManager().findFragmentById(R.id.container);
if (mNoteFragment == null) {
mNoteFragment = new NoteFragment();
getFragmentManager().beginTransaction()
.replace(R.id.container, mNoteFragment).commit();
}
//restore SharedPreferences
SharedPreferences sharedPrefs = getPreferences(0);
int stylePref = sharedPrefs.getInt(SharedPreferanceConstants.PREF_FONT_SIZE, 2);
String fontPref = sharedPrefs.getString(SharedPreferanceConstants.PREF_TYPEFACE, "");
Log.e("STYLEID", String.valueOf(stylePref));
Log.e("FONTTYPE", fontPref);
onStyleChange(null , stylePref); //NULL POINTER EXCEPTION HERE
onFontChange(null, fontPref);
The logs output "3" and "Impact" which are the correct values for size and font which indicates that stylePref and fontPref are not null.
The next Null Pointer is below.:
#Override
public void onStyleChange(CustomStyleDialogFragment dialog, int styleId) {
Log.d("NOTEFRAGMENT", String.valueOf(mNoteFragment));
mNoteFragment.setCustomStyle(styleId); //NULL POINTER EXCEPTION HERE
}
#Override
public void onFontChange(CustomStyleDialogFragment dialog, String fontName) {
mNoteFragment.setCustomFont(fontName);
}
I have tested logging the value of styleId and got "3" so that doesn't seem to be the issue. mNoteFragment isnt null either based on the log.
Here is the third NP Exception in the NoteFragment.java. This is where I ultimately set the EditText view to the desired settings. I had no trouble changing font and size without shared preferences so I am not sure the issue here.
public void setCustomFont(String fontName) {
if(fontName.equals("Helvetica")) {
mEditText.setTypeface(mHelvetica);
}
else if(fontName.equals("Helvetica-Neue")) {
mEditText.setTypeface(mHelveticaNeue);
}
else if(fontName.equals("Impact")) {
mEditText.setTypeface(mImpact);
}
else {
mEditText.setTypeface(Typeface.DEFAULT);
}
}
public void setCustomStyle(int styleId) {
if(styleId == 1) {
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Small);
}
else if(styleId == 2) {
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Medium);
}
else if(styleId == 3) {
//NULL POINTER EXCEPTION HERE
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Large);
}
}
And of course, here is the logcat. Thanks in advance!
11-18 10:31:53.030 18966-18966/com.richluick.blocnotes I/Process﹕ Sending signal. PID: 18966 SIG: 9
11-18 10:35:32.838 19248-19248/com.richluick.blocnotes D/STYLEID﹕ 3
11-18 10:35:32.838 19248-19248/com.richluick.blocnotes D/FONTTYPE﹕ Impact
11-18 10:35:32.839 19248-19248/com.richluick.blocnotes D/ERROR﹕ NoteFragment{422972f8 id=0x7f090001}
11-18 10:35:32.840 19248-19248/com.richluick.blocnotes D/AndroidRuntime﹕ Shutting down VM
11-18 10:35:32.840 19248-19248/com.richluick.blocnotes W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x4197dd40)
11-18 10:35:32.842 19248-19248/com.richluick.blocnotes E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.richluick.blocnotes, PID: 19248
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.richluick.blocnotes/com.richluick.blocnotes.BlocNotes}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2198)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5097)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.richluick.blocnotes.NoteFragment.setCustomStyle(NoteFragment.java:86)
at com.richluick.blocnotes.BlocNotes.onStyleChange(BlocNotes.java:139)
at com.richluick.blocnotes.BlocNotes.onCreate(BlocNotes.java:61)
at android.app.Activity.performCreate(Activity.java:5248)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
            at android.app.ActivityThread.access$800(ActivityThread.java:139)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5097)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
NoteFragment.java
public class NoteFragment extends Fragment {
public EditText mEditText;
private Typeface mHelvetica;
private Typeface mHelveticaNeue;
private Typeface mImpact;
private static final String TEXT = "text";
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(TEXT, mEditText.getText().toString());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_note, container, false);
setHasOptionsMenu(true);
//restore state of app when activity is destroyed and restarted
mEditText = (EditText) rootView.findViewById(R.id.editText);
if (savedInstanceState != null) {
mEditText.setText(savedInstanceState.getString(TEXT));
}
//Store the font assets as variables
mHelvetica = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Helvetica_Reg.ttf");
mHelveticaNeue = Typeface.createFromAsset(getActivity().getAssets(), "fonts/HelveticaNeue_Lt.ttf");
mImpact = Typeface.createFromAsset(getActivity().getAssets(), "fonts/impact.ttf");
return rootView;
}
/**
* This is a setter method for setting the font the user has selected from the spinner
*
* param fontName the name of the font the user selected
* #return void
* */
public void setCustomFont(String fontName) {
if(fontName.equals("Helvetica")) {
mEditText.setTypeface(mHelvetica);
}
else if(fontName.equals("Helvetica-Neue")) {
mEditText.setTypeface(mHelveticaNeue);
}
else if(fontName.equals("Impact")) {
mEditText.setTypeface(mImpact);
}
else {
mEditText.setTypeface(Typeface.DEFAULT);
}
}
/**
* This is a setter method for setting the font style the user has selected from custom menu
*
* param styleId the integer id of the font stlye selected (SMALL, MEDIUM, LARGE)
* #return void
* */
public void setCustomStyle(int styleId) {
if(styleId == 1) {
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Small);
}
else if(styleId == 2) {
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Medium);
}
else if(styleId == 3) {
Log.d("EDITTEXT", String.valueOf(mEditText));
mEditText.setTextAppearance(getActivity(), android.R.style.TextAppearance_Large);
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
super.onCreateOptionsMenu(menu, inflater);
inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.bloc_notes, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_erase) {
mEditText.setText("");
}
return super.onOptionsItemSelected(item);
}
}
In your SomeActivity.onCreate() you are creating an instance of NoteFragment, but even if you commit it via a transaction, it won't be inflated and created right away. Which basically means, the NoteFragment.onCreateView() was not executed and the fragments UI is not yet created. However, your Activity.onCreate() assumes, that mFragment.mEditText is already set, which is not the case, so you run into a NullPointerException.
Take a look at the FragmentTransation.commit method: http://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#commit()
Schedules a commit of this transaction. The commit does not happen immediately; it will
be scheduled as work on the main thread to be done the next time that thread is ready.
Your mEditText in your NoteFragment is null at this time, hence the NPE.
Just init your member mEditText in onCreate() or onActivityCreated() of the fragment, not onCreateView(). That should ensure that mEditText is not null when you call your setters.
Whatever happens, you should be protecting against a null mEditText in your setter functions.
EDIT this is what I meant:
public void setCustomFont(String fontName) {
if(mEditText != null){
if(fontName.equals("Helvetica")) {
mEditText.setTypeface(mHelvetica);
}
else if(fontName.equals("Helvetica-Neue")) {
mEditText.setTypeface(mHelveticaNeue);
}
else if(fontName.equals("Impact")) {
mEditText.setTypeface(mImpact);
}
else {
mEditText.setTypeface(Typeface.DEFAULT);
}
}
}
EDIT 2: Oncreate will not be a good place. Basically you want to call your setter after the fragmentmanager has committed your change, so that mEditText has been initialized.
EDIT 3 - Try this with your initial code:
getFragmentManager().beginTransaction().replace(R.id.container, mNoteFragment).commit();
getFragmentManager().executePendingTransactions();
Okay so I am not sure why this works but I was able to figure out the anwer based on this question:
onCreateView() in Fragment is not called immediately, even after FragmentManager.executePendingTransactions()
I added the following line
getFragmentManager().executePendingTransactions();
and then moved everthing to the onStart method
#Override
protected void onStart() {
super.onStart();
//create a new note fragment if one has not been created yet
mNoteFragment = (NoteFragment) getFragmentManager().findFragmentById(R.id.container);
if (mNoteFragment == null) {
mNoteFragment = new NoteFragment();
getFragmentManager().beginTransaction().replace(R.id.container, mNoteFragment).commit();
getFragmentManager().executePendingTransactions();
}
//restore SharedPreferences
SharedPreferences sharedPrefs = getPreferences(0);
int stylePref = sharedPrefs.getInt(SharedPreferanceConstants.PREF_FONT_SIZE, 2);
String fontPref = sharedPrefs.getString(SharedPreferanceConstants.PREF_TYPEFACE, "");
Log.d("STYLEID", String.valueOf(stylePref));
Log.d("FONTTYPE", fontPref);
onStyleChange(null , stylePref);
onFontChange(null, fontPref);
}
and for some reason it works fine now. If anyone could explain why that would be great
Try use 'apply' instead of 'commit' , the justification is here -> What's the difference between commit() and apply() in Shared Preference by Lukas Knuth.
But basically, apply() will commits its changes to the in-memory SharedPreferences immediately.
It's strong recommended use a class to manager your preferences, like 'MyPreferencesManager'.

Categories

Resources