Class not found when unmarshalling in PreferenceFragment - java

I try to implement a day/night system changeable directly from the settings. I used PreferenceFragmentCompat for this but however, when I press the switch preference to change the mode. I have the following error:
E/Parcel: Class not found when unmarshalling: androidx.fragment.app.FragmentManagerState
java.lang.ClassNotFoundException: androidx.fragment.app.FragmentManagerState
Caused by: java.lang.ClassNotFoundException: androidx.fragment.app.FragmentManagerState
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
I looked everywhere but I don't really understand where the error comes from..
This is my Preference Activity:
public class PreferencesActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
if (savedInstanceState == null)
getSupportFragmentManager().beginTransaction().replace(R.id.preferences_container, new PreferencesFragment()).commit();
}
#Override
protected void onDestroy() {
super.onDestroy();
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.contains(getString(R.string.KEY_PREF_NIGHT_MODE)))
AppCompatDelegate.setDefaultNightMode(sharedPreferences.getBoolean(key, false)? AppCompatDelegate.MODE_NIGHT_YES: AppCompatDelegate.MODE_NIGHT_NO);
}
public static class PreferencesFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
}
}
And I use this layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/noteRecyclerBackground"
tools:context=".PreferencesActivity">
<FrameLayout
android:id="#+id/preferences_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
</LinearLayout>

There is no crash but an error and this is when the activity restart with AppCompatDelegate.setDefaultNightMode(sharedPreferences.getBoolean(key, false)? AppCompatDelegate.MODE_NIGHT_YES: AppCompatDelegate.MODE_NIGHT_NO);
Well, per the documentation, this sounds like expected behavior.
If this method is called after any host components with attached AppCompatDelegates have been 'created', a uiMode configuration change will occur in each. This may result in those components being recreated, depending on their manifest configuration.

Related

FragmentTransaction.replace() crashes - but only in release build

when I execute the following code in debug (ADB via USB) it works, but when I install a generated release .apk, it crashes. More precisely the following code crashes.
.replace(R.id.settings, new SettingsFragment())
Here is the full version of the code.
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
}
I found the error from the Google Play which says it throws an IllegalStateExcetion. I do not know any other way of retrieving error messages since it works perfectly fine in debug mode.
This is the corresponding XML file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
I believe disabling Instant run may resolve this. Take a look at this thread:
Android App Crashes on Real Device If apk is manually installed
Had to make SettingsFragment public, now it looks like it works.

Using Butterknife with BaseActivity/Child Activities and MaterialDrawer

I'm facing issues implementing MaterialDrawer (library MikePenz) using Multiple Activities ( not using fragments) which is implemented with a BaseActivity. Also, using ButterKnife to bind the views.
Found related issues here in SO and tried it out one by one , but in my case it was not working since most of them using standard Navigation Drawer with Fragments or they are not related with ButterKnife.
Code :
MainActivity class
public class MainActivity extends AppCompatActivity {
#BindView(R.id.toolbar)
Toolbar toolbar;
private List<TestModel> destinations;
private DestinationAdapter mAdapter;
ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
navManagement();
}
}
activity_main layout
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/maincontainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tvs.ui.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay"
/>
</android.support.design.widget.AppBarLayout>
</android.support.constraint.ConstraintLayout>
StoreActivity
public class StoresActivity extends MainActivity {
#BindView(R.id.searchEditText)
EditText mSearchEditText; // errorRequired view 'searchEditText' with ID 2131558557 for field 'mSearchEditText' was not found
#BindView(R.id.storesRecyclerView)
RecyclerView recyclerView; // here too
private List<TestModel> stores;
private StoreAdapter mAdapter;
//endregion
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stores);
ButterKnife.bind(this);
loadRecyclerView();
testData();
}
}
activity_store layout
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/searchEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/storesRecyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
I understand that cause of error is that the ButterKnife.Bind in MainActivity is called when the Layout is inflated but the Views are not inflated in the inherited Activities . The Navigation drawer loads but on clicking item it fails as obvious reason. I cannot use a FrameLayout since I'm using MaterialDrawer library which doesn't ( or I'm not aware) have views to inflate.
I tried several methods extensively searching SO like SO1SO2 Git Git2
Link but was not successful .
Appreciate any help are deeply appreciated . Thanks in advance.
Thanks #mikepenz for the response.
Posting it since it might help somebody
The issue was fixed by creating an abstract method in BaseActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
ButterKnife.bind(this);
setSupportActionBar(toolbar);
navManagement();
}
protected abstract int getLayoutResourceId();
Concrete Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_stores); not required
ButterKnife.bind(this);
loadRecyclerView();
testData();
}
#Override
protected int getLayoutResourceId() {
return R.layout.activity_stores;
}
Please note that I was not using ButterKnife.Bind in the Concrete Activity and used #Nullable fields. But currently Binding in both Base and Implementing Activities.
The MaterialDrawer will inflate views to your layout. By default it will add a DrawerLayout into the root of your activity, and add the other content (which is your main layout) as child to it again.
This decision was made to make it super simple to implement a Drawer into your application without needing to alter anything special.
Butterknife will bind the view's at the time you call the bind method.
All views of the MaterialDrawer, are bound at the time of you calling .build(), but as the views of the MaterialDrawer are bound internally you shouldn't have to worry about these.
To complete #user2695433 's answer, you can go a little futher : handle all butterknife init and close in the BaseActivity so you can't forget to release ressources ! Very useful if some new dev come in your team and dont know how butterknife work. Here it is :
--------In BaseActivity-------
protected Unbinder binder;
protected abstract int getLayoutResourceId();
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
binder = ButterKnife.bind(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
binder.unbind(); //release ressource
}
----- In ConcreteActivity------------
#BindView(R.id.title)
TextView title; // butterknife stuff
#Override
protected int getLayoutResourceId() { //define which Id
return R.layout.activity_main;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

Can't see the map from the HelloWorld example ArcGIS android SDK

I tried the Hello World code from ArcGIS android SDK and followed all the steps but the map doesn't appear and instead I get a black mapview.
Here is the java code :
package com.example.user.arcgismap;
import android.app.Activity;
import android.os.Bundle;
import com.esri.android.map.MapView;
public class MainActivity extends Activity {
MapView mMapView;
// Called when the activity is first created.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
// After the content of this Activity is set, the map can be accessed programmatically from the layout.
mMapView = (MapView) findViewById(R.id.map);
}
#Override
protected void onPause() {
super.onPause();
// Call MapView.pause to suspend map rendering while the activity is paused, which can save battery usage.
if (mMapView != null)
{
mMapView.pause();
}
}
#Override
protected void onResume() {
super.onResume();
// Call MapView.unpause to resume map rendering when the activity returns to the foreground.
if (mMapView != null)
{
mMapView.unpause();
}
}
}
and here is the xml layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.user.arcgismap.MainActivity"
tools:showIn="#layout/activity_main">
<com.esri.android.map.MapView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
mapoptions.MapType="streets"
mapoptions.center="34.056215, -117.195668,"
mapoptions.ZoomLevel="16">
</com.esri.android.map.MapView>
</RelativeLayout>
can anyone help, what am I doing wrong ?
apparently the code is working well all I had to do was to reinstall the apk and wait a little bit for the map to load. I guess patience is a virtue.

Android Change text in TextView

I'm trying to change the text in my TextView by using the setText().
When I try to do this I get the following error:
E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{<bla bla bla>}: java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at com.training.mytraining.test.MainActivity.display(MainActivity.java:35)
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView tvCountry;
private Server theServer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvCountry = (TextView) findViewById(R.id.countryTextView);
theServer = new Server(this);
theServer.weatherFromYahoo();
}
public void display() {
tvCountry.setText("USA");
}
}
Server.java
public class Server extends AppCompatActivity {
MainActivity theMainActivity;
//Constructor
public Server (Context context){
this.theMainActivity = new MainActivity();
}
public void weatherFromYahoo() {
theMainActivity.display();
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="#+id/countryTextView"
android:text="#string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
This is just an example of my real code. I did'nt want to put all the code, so I made a new code with just that problem I get. I have to set the text by calling my MainActivity from an another class.
Please help me, I have been stuck here for hours.
Change this:
public Server (Context context){
this.theMainActivity = new MainActivity();
}
To this:
public Server (Context context){
this.theMainActivity = (MainActivity)context;
}
So that the onCreate is called properly still. If you are new'ing up an activity, it won't be able to set the view properly and follow the correct lifecycle. As #CommonsWare says, you shouldn't ever create an activity via its constructor.

Why Fragment cannot be public static class?

I came across such problem: I wanted to have some Fragment as public static member of my Activity class.
But when I put such Fragment to layout file I receive such exception:
Caused by: android.support.v4.app.Fragment$InstantiationException:
Unable to instantiate fragment com.tst.MainActivity.InnerFragment:
make sure class name exists, is public,
and has an empty constructor that is public
...
My code looks like this:
package com.tst;
public final class MainActivity extends SherlockFragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public static class InnerFragment extends SherlockFragment {
public InnerFragment() {
super();
}
...
}
}
Layout file looks like this:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<fragment
android:id="#+id/inner_fragment"
android:name="com.tst.MainActivity.InnerFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Now my question is why such code throws this Exception? As Android should be able to instanitate InnerFragment as it is public static. What is more I used to use public static Fragments and they worked, but on that time I added them programmatically in code not in xml definition.
Regards,
Michal
Change
android:name="com.tst.MainActivity.InnerFragment"
to
android:class="com.tst.MainActivity$InnerFragment"

Categories