I am having troubles with my Fragments. I have four fragments which were in portrait mode.
Setting the fragments
public void setCorrectNavigationItem(int id) {
if (id == R.id.nav_auftragsbilder) {
fragment = new AuftragsbilderFragment();
id = R.id.nav_auftragsbilder;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (id == R.id.nav_auftragskorrektur) {
fragment = new AuftragskorrekturFragment();
id = R.id.nav_auftragskorrektur;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (id == R.id.nav_lagerplatz) {
fragment = new LagerplatzFragment();
id = R.id.nav_lagerplatz;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (id == R.id.nav_biegenstatus) {
fragment = new BiegestatusFragment();
id = R.id.nav_biegenstatus;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
_navigationView.setCheckedItem(id);
_selectedMenuItem = id;
SharedPreferences.Editor editor = menuCheck.edit();
editor.putInt("id", id);
editor.commit();
//Fragment öffnen
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.fragment_container, fragment);
ft.commit();
}
}
So in my fragment setting method I now have to set the orientation for each different fragment. I had to change my 'BiegestatusFragment' to landscape, there I am calling a method which is scanning barcodes, on intent result I set parameters in my Fragment.
Here is my Barcode-Scanning Activity
//Biegestatus Begleitschein-Barcodes
public void makeBiegestatusBegleitscheinBarcode() {
_lastAction = ACTION_BIEGESTATUS_BEGLEITSCHEIN_BARCODE;
if (!checkCameraPermission(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
} else {
Intent intent = new Intent(this, ContinuousCaptureActivity.class);
startActivityForResult(intent, 1);
}
}
Intent Result
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
ArrayList<String> begleitscheine = data.getStringArrayListExtra("begleitscheine");
if (resultCode == 1 && begleitscheine != null) {
//HERE IT IS NULL
((BiegestatusFragment) fragment).setBegleitscheine(begleitscheine);
} else {
Toast.makeText(this, "Scannen abgebrochen", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(this, "Unbekannter Fehler aufgetreten, Entwickler kontaktieren.", Toast.LENGTH_LONG).show();
}
}
Fragments onCreateView
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_biegestatus, container, false);
_cardEdit = (EditText) v.findViewById(R.id.workerEdit);
_scrollViewArticles = (ScrollView) v.findViewById(R.id.scrollViewArticles);
_searchImageLayout = (LinearLayout) v.findViewById(R.id.searchImageLayout);
_personalNummer = (EditText) v.findViewById(R.id.workerEdit);
_progressBar = (LinearLayout) v.findViewById(R.id.progressBar);
_maschinenPicker = (NumberPicker) v.findViewById(R.id.maschinenPicker);
_pickerHolder = (LinearLayout) v.findViewById(R.id.pickerHolder);
_scanBegleitscheinBtn = (Button) v.findViewById(R.id.scanBegleitscheinBtn);
return v;
}
Method should be called
public void setBegleitscheine(ArrayList<String> begleitscheine) {
_begleitscheine = begleitscheine;
}
Now my Fragment is null because of the orientation change.
Removing the orientation setting methods solves my problem. But I need to have this fragment in landscape.
Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: at.co.era.bilder.erabilderapp, PID: 21835
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=1, data=Intent { launchParam=MultiScreenLaunchParams { mDisplayId=0 mBaseDisplayId=0 mFlags=0 }(has extras) }} to activity {at.co.era.bilder.erabilderapp/at.co.era.bilder.erabilderapp.HomeActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void at.co.era.bilder.erabilderapp.BiegestatusFragment.setBegleitscheine(java.util.ArrayList)' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4520)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4563)
at android.app.ActivityThread.-wrap22(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1698)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void at.co.era.bilder.erabilderapp.BiegestatusFragment.setBegleitscheine(java.util.ArrayList)' on a null object reference
at at.co.era.bilder.erabilderapp.HomeActivity.onActivityResult(HomeActivity.java:1130)
at android.app.Activity.dispatchActivityResult(Activity.java:7280)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4516)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4563)
at android.app.ActivityThread.-wrap22(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1698)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
//Fragment öffnen
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.fragment_container, fragment);
ft.addToBackStack(null); // or you can give it any name instead of null to get the frament when poping the fragment from backstack
ft.commit();
}
You can force your activity not to reload after orientation changed by adding the following line in manifest to your activity tag
android:configChanges="orientation"
Inside fragment ,in onCreateView() try using :
setRetainInstance(true);
Check the doc here :
https://developer.android.com/reference/android/app/Fragment#setRetainInstance(boolean)
Related
I found this code to pass the data from a fragment to another:
Fragment 1:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment2 fragment2 = new Fragment2();
Bundle bundle = new Bundle();
bundle.putString("data", data);
fragmentTransaction.replace(R.id.fragment_container, fragment2);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Fragment 2:
Bundle bundle = getArguments();
assert bundle != null;
String data = bundle.getString("data");
But I dont want to change the fragment. So I removed parts of it. But it doesnt work. Here my code:
Fragment 1:
public void openActifity2(){
Fragment_score fragment_score = new Fragment_score();
Bundle bundle = new Bundle();
bundle.putInt("FINISHED_LEVELS", finishedLevels);
bundle.putInt("FAILED_LEVELS", failedLevels);
bundle.putInt("SKIPPED_LEVELS", skippedLevels);
bundle.putInt("USED_HINTS", usedHints);
fragment_score.setArguments(bundle);
}
Fragment 2:
Bundle bundle = getArguments();
int finishedLevels = bundle.getInt("FINISHED_LEVELS");
int failedLevels = bundle.getInt("FINISHED_LEVELS");
int skippedLevels = bundle.getInt("FINISHED_LEVELS");
int usedHints = bundle.getInt("FINISHED_LEVELS");
Do I have to use the code I found on the internet or does my version work too?
I get this error when I open the second fragment:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.rexan_snerficonquiz, PID: 20931
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.Bundle.getInt(java.lang.String)' on a null object reference
at com.example.rexan_snerficonquiz.Fragment_score.onCreateView(Fragment_score.java:26)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
in order to avoid getting the error, try this
Bundle bundle = getArguments();
if(bundle != null){
int finishedLevels = bundle.getInt("FINISHED_LEVELS", "DEFAULT_VALUE");
int failedLevels = bundle.getInt("FINISHED_LEVELS", "DEFAULT_VALUE");
int skippedLevels = bundle.getInt("FINISHED_LEVELS", "DEFAULT_VALUE");
int usedHints = bundle.getInt("FINISHED_LEVELS", "DEFAULT_VALUE");
}
Based on your comments, you can change fragment in onOptionsItemSelected method
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_1) {
// add your action here that you want
return true;
}else if (id==R.id.action_2) {
// add your action here that you want
return true;
}
return super.onOptionsItemSelected(item);
}
If you change the fragments than your code will be working fine. But if you don't want to change fragments than 1) int finishedLevels = bundle.getInt("FINISHED_LEVELS", 0); OR 2) Instead of bundle use static global variables public static int finishedLevels = 0; in Fragment 1 and then simply get their value in Fragment 2 using class name reference.
Note: If you don't want to change the fragment and want values in Fragment 2 then i would recommend the static variables
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I'm writing a program to save user input from the edit text and inserting the text into a listview. I keep getting this null exception even though I've declared the Edit Text already.
public class AddEditAlbum extends AppCompatActivity {
/**
* These keys are to send back and forth information between the bundles and intents
*/
public static final String ALBUM_INDEX = "albumIndex";
public static final String ALBUM_NAME = "albumName";
EditText input;
Button save, cancel;
int albumIndex;
#Override
protected void onCreate(Bundle savedInstanceState) {
save = (Button) findViewById(R.id.save);
cancel = (Button) findViewById(R.id.cancel);
input = (EditText) findViewById(R.id.add);
// see if info was passed in to populate field
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
albumIndex = bundle.getInt(ALBUM_INDEX);
input.setText(bundle.getString(ALBUM_NAME));
}
super.onCreate(savedInstanceState);
setContentView(R.layout.add_album);
}
public void Cancel(View view) {
setResult(RESULT_CANCELED);
finish(); //Returns to previous page on call stack
}
public void addAlbum(View view){
String name = input.getText().toString(); //Fix this, goes to null pointer
//Checks to see if input is null and returns
if(name == null || name.length()==0){
Toast.makeText(AddEditAlbum.this, "Enter valid album name", Toast.LENGTH_SHORT).show();
Bundle bundle = new Bundle();
bundle.putString(AlbumDialog.MESSAGE_KEY, "Album Name Required");
DialogFragment newFragment = new AlbumDialog();
newFragment.setArguments(bundle);
newFragment.show(getFragmentManager(), "badfields");
return;
}
//Toast.makeText(AddEditAlbum.this, "Enter valid album name", Toast.LENGTH_SHORT).show();
Bundle bundle = new Bundle();
bundle.putInt(ALBUM_INDEX, albumIndex);
bundle.putString(ALBUM_NAME, name);
// send back to caller
Intent intent = new Intent();
intent.putExtras(bundle);
setResult(RESULT_OK,intent);
finish();
}
}
public class MainActivity extends AppCompatActivity {
ListView listView;
private ArrayList<Album> albums;
public static final int EDIT_ALBUM_CODE = 1;
public static final int ADD_ALBUM_CODE = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
listView = (ListView) findViewById(R.id.album_list);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void Create(View view){
Intent intent = new Intent(this, AddEditAlbum.class);
startActivityForResult(intent, ADD_ALBUM_CODE);
}
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode != RESULT_OK) {
return;
}
Bundle bundle = intent.getExtras();
if (bundle == null) {
return;
}
// gather all info passed back by launched activity
String name = bundle.getString(AddEditAlbum.ALBUM_NAME);
int index = bundle.getInt(AddEditAlbum.ALBUM_INDEX);
if (requestCode == EDIT_ALBUM_CODE){
Album album = albums.get(index);
album.albumName = name;
}
else if (requestCode == ADD_ALBUM_CODE){
ArrayList<Photo> photos = new ArrayList<>();
albums.add(new Album(name, photos));
}
// redo Adapter since source content has changed
//listView.setAdapter(new ArrayAdapter<Album>(this, album, albums));
}
So this is the full error I'm getting,
FATAL EXCEPTION: main
Process: com.example.mustu.androidphotos31, PID: 9965
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22265)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22265)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
at com.example.mustu.androidphotos31.AddEditAlbum.addAlbum(AddEditAlbum.java:54)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22265)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
super.onCreate(savedInstanceState);
setContentView(R.layout.add_album);
This has to be executed first, otherwise the contentView is not set and findViewById will not find anything, resulting in the EditText being null.
update your onCreate() like this.
we should call setContentView(R.layout.your_layout) for passing the layout to the java class, then only it's views can be used.. failing to do so, will lead to NPE.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_album);
save = (Button) findViewById(R.id.save);
cancel = (Button) findViewById(R.id.cancel);
input = (EditText) findViewById(R.id.add);
// see if info was passed in to populate field
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
albumIndex = bundle.getInt(ALBUM_INDEX);
input.setText(bundle.getString(ALBUM_NAME));
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.album_list);
}
Also You are calling your listview before onCreate method thus giving you a NPE
So I'm working on an app and I had this part working for days, and out of no where it just stopped working for no reason...
I also had the same error when I was trying to use another headless fragment in my MainActivity, but ended up replacing the fragment with inner methods inside of the MainActivity and everything went back to working properly.
However, I can't rewrite every bit of code I have just to avoid using fragments. The fragment code is below.
public class IMEIFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback{
public static final String TAG_IMEI = "IMEILoader";
protected Activity mActivity;
private String RecordedIMEI;
//public static final String CHECK_INTERNET = "network_connection";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return null; //Do we need this at all?
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
Activity activity = context instanceof Activity ? (Activity) context : null;
mActivity = activity;
}
//Is this needed?
#SuppressWarnings("deprecation")
#Override
public void onAttach(Activity activity) {
activity = getActivity();
if (isAdded() && activity != null) {
super.onAttach(activity);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mActivity = activity;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
public String loadIMEI(Context context) {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// READ_PHONE_STATE permission has not been granted.
requestPermissions(context);
} else {
// READ_PHONE_STATE permission is already been granted.
RecordedIMEI = permissionGrantedActions(context);
}
if (RecordedIMEI != null) {
Log.i("loadIMEIService", "IMEI number returned!");
}
} else {
// READ_PHONE_STATE permission is already been granted.
RecordedIMEI = permissionGrantedActions(context);
}
if (RecordedIMEI != null) {
Log.i("loadIMEIService", "IMEI number returned!");
}
return RecordedIMEI;
}
private void requestPermissions(Context context) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
Log.i("loadIMEIService", "READ_PHONE_STATE permission not granted, asking for it...");
// TODO create proper notification content
PermissionHelper.requestPermissions(((PriceActivity) getActivity()),
new String[]{Manifest.permission.READ_PHONE_STATE},
Constants.PERM_REQUEST_PHONE_STATE,
getString(R.string.notify_perm_title),
getString(R.string.notify_perm_body),
R.drawable.ic_security);
}
}
// Callback received when a permissions request has been completed.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
boolean isGranted = false;
for (int i = 0; i < grantResults.length; i++)
if (permissions[i].equals(Manifest.permission.READ_PHONE_STATE) && (grantResults[i] == PackageManager.PERMISSION_GRANTED))
isGranted = true;
if (isGranted) {
Context context = getActivity().getApplicationContext();
permissionGrantedActions(context);
}
else
Log.w("loadIMEIService", "READ_PHONE_STATE permission not granted. loadIMEI will not be available.");
}
public String permissionGrantedActions(Context context) {
//Have an object of TelephonyManager
TelephonyManager tm =(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//Get IMEI Number of Phone
String IMEINumber = tm.getDeviceId();
if(IMEINumber != null) {
Log.i("loadIMEIService", "IMEI number recorded!");
}
return IMEINumber;
}
}
Error is below:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.project1, PID: 5498
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.project1/com.android.project1.main.MainActivity}: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:805)
at android.app.Fragment.getString(Fragment.java:827)
at com.android.project1.fragments.IMEIFragment.requestPermissions(IMEIFragment.java:107)
at com.android.project1.fragments.IMEIFragment.loadIMEI(IMEIFragment.java:80)
at com.android.project1.main.MainActivity.onCreate(MainActivity.java:108)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
And here's the relevant part of my MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDeviceCode = (TextView) findViewById(R.id.device_code);
// Initializing headless fragment
mFragment =
(IMEIFragment) getFragmentManager()
.findFragmentByTag("IMEILoader");
if (mFragment == null) {
mFragment = new IMEIFragment();
getFragmentManager().beginTransaction()
.add(mFragment, "IMEILoader").commit();
}
if (mFragment != null) {
mNumber = mFragment.loadIMEI(MainActivity.this);
mDeviceCode.setText(Html.fromHtml("<b>IMEI</b>: " + mNumber));
}
I literally had the exact same code working for over a week. Anyone knows what could be the problem?
Edit 1: The error is pointing to requestPermissions inside my fragment
Fragments should be self contained as much as possible. You are calling directly into your IMEIFragment from the activity,
Caused by: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:805)
at android.app.Fragment.getString(Fragment.java:827)
at com.android.project1.fragments.IMEIFragment.requestPermissions(IMEIFragment.java:107)
at com.android.project1.fragments.IMEIFragment.loadIMEI(IMEIFragment.java:80)
at com.android.project1.main.MainActivity.onCreate(MainActivity.java:108)
You can't do that. Adding the fragment via a transaction from the activity is an asynchronous operation. E.g., when the commit() method completes, the fragment is not initialized. Moreover, you have no way of knowing when it's initialized. That's why it should be self contained. The fragment decides when to call loadIMEI(), not the activity.
If you really need it to be initiated by the activity, you can add a callback from the fragment to the activity like,
void onFragmentReady(Fragment f);
Or something.
And yes, onCreateView() should return something. If your fragment really doesn't have any UI at all, you don't need it to be a fragment.
I'm trying to implement a preference fragment in my app, so I set preferences.xml file, fragment that is supposed to show preferences, and fragment transaction. When I try to show SettingsFragment, the app crashes with this error log:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:431)
at android.support.v4.app.BackStackRecord.replace(BackStackRecord.java:481)
at android.support.v4.app.BackStackRecord.replace(BackStackRecord.java:472)
at com.ikurek.pwr.MainActivity.onNavigationItemSelected(MainActivity.java:145)
at android.support.design.widget.NavigationView$1.onMenuItemSelected(NavigationView.java:153)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:810)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:957)
at android.support.design.internal.NavigationMenuPresenter$1.onClick(NavigationMenuPresenter.java:328)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
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:5254)
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:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Why is this object null? How else am I supposed to set up a setting fragment? I know that solution for this is proably very simple, but somehow I cannot figure this out by myself. Here's my code:
Part that calls fragment transaction from MainActivity:
public boolean onNavigationItemSelected(MenuItem item) {
Fragment fragment = null;
Class fragmentClass = null;
int id = item.getItemId();
if (id == R.id.nav_news) {
fragmentClass = NewsFragment.class;
} else if (id == R.id.nav_map) {
fragmentClass = CatFragment.class;
} else if (id == R.id.nav_buildings) {
fragmentClass = BuildingsFragment.class;
} else if (id == R.id.nav_settings) {
fragmentClass = SettingsFragment.class;
} else if (id == R.id.nav_info) {
fragmentClass = AppInfoFragment.class;
} else if (id == R.id.nav_bugreport) {
fragmentClass = ContactFragment.class;
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frameLayoutForFragments, fragment).commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
My preferences.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="saveLastPosition"
android:summary="1st check box"
android:title="Check"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="keepScreenOn"
android:summary="2nd check box"
android:title="Box"/>
</PreferenceScreen>
And my SettingsFragment:
public class SettingsFragment extends PreferenceFragment {
public SettingsFragment() {
// Required empty public constructor
}
public static SettingsFragment newInstance() {
SettingsFragment fragment = new SettingsFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
Well from what I can tell you are passing a null fragment to your fragment manager. As you will notice:
Fragment fragment = null;
Class fragmentClass = SettingsFragment.class;
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frameLayoutForFragments, fragment).commit();
You have:
Fragment fragment = null;
You never actually declare this as a SettingsFragment. You should either have:
Fragment fragment = new SettingsFragment();
Or declare it in your replace statement.
Class fragmentClass = SettingsFragment.class;
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frameLayoutForFragments, new SettingsFragment()).commit();
Users of the app I am working on have a crashing issue. This is the stack trace I get from the console.
java.lang.NullPointerException: Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim' on a null object reference
at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:924)
at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1605)
at android.support.v4.app.FragmentManagerImpl$4.run(FragmentManager.java:532)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:458)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
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:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
The crash only happens with users that have Galaxy Note3 or Galaxy S4 phones with 5.x or at least those our the only one that have got reported but it has happen a lot. It seems to happen on transition between fragments or sometimes when coming back from the camera. Here are my transition methods.
public void popBackStackToOr(String popBackFragmentName, String secondPopBackFragment)
{
int backStackId = 0;
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (int k = (backStackCount - 1); k > 0; k--)
{
String aFragmentClass = fragments.get(k).getClass().toString();
String[] splitList = aFragmentClass.split("\\.");
aFragmentClass = splitList[splitList.length - 1];
boolean firstOptionTrue = aFragmentClass.equalsIgnoreCase(popBackFragmentName);
boolean secondOptionTrue = aFragmentClass.equalsIgnoreCase(secondPopBackFragment);
if ( (firstOptionTrue) || (secondOptionTrue) )
{
backStackId = getSupportFragmentManager().getBackStackEntryAt(k).getId();
break;
}
}
getSupportFragmentManager().popBackStack(backStackId, android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE); //Immediate
}
public void popBackStackForReview(String popBackFragmentName)
{
int backStackId = 0;
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (int k = (backStackCount - 1); k > 0; k--)
{
String aFragmentClass = fragments.get(k).getClass().toString();
String[] splitList = aFragmentClass.split("\\.");
aFragmentClass = splitList[splitList.length - 1];
if (aFragmentClass.equalsIgnoreCase(popBackFragmentName))
{
backStackId = getSupportFragmentManager().getBackStackEntryAt(k).getId();
break;
}
}
getSupportFragmentManager().popBackStack(backStackId, android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void transitionToLoginPage()
{
Fragment newFragment = new LoginPage();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, newFragment);
//transaction.addToBackStack(null);
transaction.commitAllowingStateLoss();
}
public void transitionToNewScreen(Fragment newFragment, Bundle bundle)
{
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (currentFragment != null)
{
transaction.remove(currentFragment);
}
currentFragment = newFragment;
if (bundle != null)
{
newFragment.setArguments(bundle);
}
transaction.replace(R.id.frame_container, newFragment);
transaction.addToBackStack("dummy");
transaction.commitAllowingStateLoss();
}
public void transitionToNewScreenAndEmptyStack(Fragment newFragment)
{
getSupportFragmentManager().popBackStack(0, android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
currentFragment = newFragment;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, newFragment);
transaction.addToBackStack(null);
transaction.commitAllowingStateLoss();
}
These are the only methods that do transition in the app. So I am assuming it is coming from one of these. But the stack trace does not go back to any code I wrote so I am not sure. I have found similar problems saying that this is a Android 5.x issue and there was no fix. So any help to remove this issue would be great
It's because you are calling remove() add() etc. methods with null value.
and please keep in mind that replace() = remove()->add() one by one.
Try to use Fragments extending android.support.v4.app.Fragment instead of android.app.Fragment and use the android.app.FragmentTransaction instead of android.support.v4.app.FragmentTransaction
This bug already solved in this question:
Trying to remove fragment from view gives me NullPointerException on mNextAnim
Try it out.