getSerializableExtra() is null randomly - android

There is a link in one activity, after I click on it it opens another activity. I add an enum parameter for the second activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
binding.myLink.setOnClickListener(new View.OnClickListener() {
// ...
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivityContext(), SecondActivity.class);
intent.putExtra(KEY, MyEnum.ENUM_VALUE);
startActivity(intent);
}
});
// ...
}
In onCreate of second activity I read this parameter
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// get value
FirstActivity.MyEnum value = (FirstActivity.MyEnum ) getIntent()
.getSerializableExtra(AboutActivity.KEY);
// ...
}
Everything works but in Crashlytics I see that for some users value is null. Second activity is called only from first one and from nowhere else.
Can someone suggest me the scenario with this behavior? When can it happen like this?
I opened my app, opened the second activity and put app to background. After several hours I opened my app from the list of apps and everything is ok. No more ideas when it can happen.

use this :
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivityContext(), SecondActivity.class);
Bundle bundle=new Bundle();
bundle.putSerializable(serializableKEY,yourSerializableClass);
intent.putExtras(KEY, bundle);
startActivity(intent);
}
});
and in second activity :
Bundle bundle=getIntent().getExtras();
yourSerializableClass clazz=(yourSerializableClass)bundle.getSerializable(serializableKEY);

Related

How do I randomly start activities?

I'm looking to randomly start activities in android studio without repetition. I'd like to be able to start an activity randomly by clicking a button and in an 'if' statement. Whoever can help out that would be fantastic! Thank you.
ArrayList<Class> activities = new ArrayList<>();
#Override
public void onCreate(Bundle savedInstanceState) {
//your codes...
activities.add(History.class);
activities.add(Bookmark.class);
activities.add(Themes.class);
//your codes
}
public void openActivity(Class class_) {
Intent intent = new Intent(this, class_);
startActivity(intent);
}
public void openRandomActivity(){
Class that = activities.get(new Random().nextInt(activities.size()));
activities.remove(that); // after using, remove from list
openActivity(that);
}
Call openRandomActivity when a user click to button.

Activity layout blinking after finish() is called

When I open my app, an Activity is started, and inside its onCreate method I'm checking some conditions. If the condition is true, I finish my current Activity and open another one. The problem is: The first activity blinks on the screen and then the second one is opened. The code is below:
public class FirstActivity extends Activity {
#Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//some code here...
checkSomeStuff();
setContentView(R.layout.my_layout);
//some code here...
}
private void checkSomeStuff() {
if (/*some condition*/) {
final Intent intent = new Intent(this, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
startActivity(intent);
}
}
}
Notice that setContentView() is after the check, but before the second activity is started, the first one still blinks on the screen.
Does anyone know how to make it not blink?
Thanks in advance.
The purpose of finish() is to destroy the current activity and remove it from the back stack. By calling finish then firing the intent, you are asking the activity to destroy it self (I assume the blink is it trying to recover) then firing the intent to the second. Move finish to after startActivity()
#Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//some code here...
if(checkSomeStuff()) {
setContentView(R.layout.my_layout);
//some code here...
}
}
private boolean checkSomeStuff() {
if (/*some condition*/) {
final Intent intent = new Intent(this, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return false;
}
return true;
}
The order of your code is wrong. You should not call anything after
finish();
This is because the activity will be destroyed. Anything following could result in strange behavior.
#Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set my layout
setContentView(R.layout.my_layout);
//some code here...
finish();
//nothing here because activity will be destroyed
}
Flicker and blinking Activity
- Reason finish();
- Remove finish() in Activity
- added android:noHistory="true" in AndroidManifest
The android:noHistory will clear Activity from stack which need to be clear on back press otherwise it shows activity A on screen.
The below-mentioned trick is working perfectly for me. Hope this could useful for others.
Opening activity B from activity A.
To close activity B I am using:
finish();
overridePendingTransition(0, 0);
to avoid the black color blinking problem.
instead of doing
checkSomeStuff();
setContentView(R.layout.my_layout);
you should do
private void checkSomeStuff() {
if (//some condition) {
final Intent intent = new Intent(this, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
startActivity(intent);
}else{
setContentView(R.layout.my_layout);
}
}
you see the view because the intent does not fire until onCreate is finished so setContentView gets called
Perhaps you can separate your condition better to entirely avoid setContentView() when you're planning to finish().
public class FirstActivity extends Activity {
#Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (someCondition()) {
goToNextActivity();
} else {
setContentView(R.layout.my_layout);
//some code here...
}
}
private boolean someCondition() {
/* return result of some condition */
}
private void goToNextActivity() {
final Intent intent = new Intent(this, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
startActivity(intent);
}
}
Try this with your style
<style name="CHTheme" parent="Theme.AppCompat.Light">
<item name="android:windowDisablePreview">true</item>
</style>

Don't understand why I'm getting NullPointerException

I don't understand why I my app keeps on crashing. According to LogCat, it is caused by a NullPointerExeption on a line, however, I cannot find why it is occurring. What's supposed to happen is an image resource for an ImageView is changed in MainActivity by pressing a button on another activity. I have followed multiple guides, but get the recurring error. From what I can see it occurs when extra information is passed through an Intent, something is null but I cannot find it.
LogCat
05-03 22:33:03.158: E/AndroidRuntime(31629): Caused by: java.lang.NullPointerException
05-03 22:33:03.158: E/AndroidRuntime(31629): at com.crackedporcelain.crackedcalibration.MainActivity.onCreate(MainActivity.java:21)
Line 21 (offender in MainActivity)
String gridPressed = content.getString("gridPressed");
Main Activity (receiver)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bundle content = getIntent().getExtras();
// Set image based on which button was pressed
String gridPressed = content.getString("gridPressed");
ImageView spotlightOne = (ImageView) findViewById(R.id.variousOne);
if (gridPressed.equals("one")) {
spotlightOne.setImageResource(R.drawable.one);
} else if (gridPressed.equals("two")) {
spotlightOne.setImageResource(R.drawable.two);
} else {
spotlightOne.setImageResource(R.drawable.one);
}
ImageView buttonGrid = (ImageView) findViewById(R.id.phoneReference);
buttonGrid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(
"com.crackedporcelain.crackedcalibration.IDENTIFICATION"));
}
});
}
Other Activity (sender)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.identification);
ImageView gridButton1 = (ImageView) findViewById(R.id.buttonImage1);
ImageView gridButton2 = (ImageView) findViewById(R.id.buttonImage2);
gridButton1.setOnClickListener(this);
gridButton2.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonImage1:
Intent oneA = new Intent(IdentificationActivity.this, MainActivity.class);
oneA.putExtra("gridPressed", "one");
startActivity(oneA);
break;
case R.id.buttonImage2:
Intent oneB = new Intent(IdentificationActivity.this, MainActivity.class);
oneB.putExtra("gridPressed", "two");
startActivity(oneB);
break;
}
}
Additional Info
Layouts for these classes are setup correctly, they work fine. It only force closes when I try to use Intents.
All help is appreciated! Thanks!
The received intent did not contain any extra values. Make sure the code sending the intent had added to the intent an extra String value with the name "gridPressed". You can use Intent.putExtra(String, String) for this purpose.
Intent.getExtras() will return null if there are no extra values. In addition, Bundle.getString(String key) will return null if the Bundle does not contain the key.
Finally, be sure to check that MainActivity is not invocable in any other way (like when the app icon is clicked). If that is possible, then this version of onCreate() will work better:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView spotlightOne = (ImageView) findViewById(R.id.variousOne);
// Set image based on which button was pressed, if any
String gridPressed = getIntent().getStringExtra("gridPressed");
if ("one".equals(gridPressed)) {
spotlightOne.setImageResource(R.drawable.one);
} else if ("two".equals(gridPressed)) {
spotlightOne.setImageResource(R.drawable.two);
} else {
spotlightOne.setImageResource(R.drawable.one);
}
ImageView buttonGrid = (ImageView) findViewById(R.id.phoneReference);
buttonGrid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(
"com.crackedporcelain.crackedcalibration.IDENTIFICATION"));
}
});
}
You're getting a NPE because you are not sending a bundle from the sender activity rather just a string extra. So, to access the String extra in the receiver activity, use :
getIntent().getStringExtra("gridPressed");
To send bundles, you need to first create a bundle, then add extras to that bundle and then pass the bundle with the intent :
Bundle bundle = new Bundle();
bundle.putString("KEY", "VALUE");
intent.putExtras(bundle);
If you send a bundle as mentioned in 2, your existing code in the receiving activity will work, otherwise you can change the code in the receiving activity as mentioned in 1.

Android back button not going right activity And How to handle Activities in Android

Am creating small application using login, register and user details. After login am going to store login credential to shared preference and navigate to dashboard activity. In second time directly navigate to dashboard activity. This level of code is working fine.
Please consider I have three activity MainActivity, LoginActivity, RegisterActivity, DashboardActivity and ProfileActivity.
In my MainActivity If user value is sharedPreference directly moving to DashboardActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(new SessionManager(getApplicationContext()).isLoggedIn()){
startActivity(new Intent(getApplicationContext(), DashboardActivity.class));
}
}
In my DashboardActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageButton imgBtn = (ImageButton) findViewById(R.id.imageButton1);
imgBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
}
});
}
Now am simply press back button in device goes to MainActivity not DashboardActivity. I want to move activity to DashboardActivity only, not MainActivity. Please guide me how to do that. And how to handle session in Android.
Also I have bit confusion in using which flags and where to use. I tried in DashboardActivity but not working.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageButton imgBtn = (ImageButton) findViewById(R.id.imageButton1);
imgBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent newIntent = new Intent(getApplicationContext(), ProfileActivity.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
}
});
}
Now I tried various possible ways but not getting solution.
Main problem occurs after navigating DashboardActivity to any Activity won't come back to DashbarodActivity instead of going MainActivity. I don't know why it happens. Any problem in MainActivity navigation
I'm not sure about that, but in DashboardActivity try to start your activity like this: startActivity(new Intent(DashboardActivity.this, ProfileActivity.class));
Just finish the current activity after starting the new one via Intent and you should achieve the desired functionality and this way you don't need any flags. Except for the MainActivity of course.
Just simply override onBackPressed method in your ProfileActivity and call finish method.
#Override
public void onBackPressed() {
finish();
}
EDITED ANSWER:
on your ProfileActivity, try to override onBackPressed method then start the DashboardActivity again and don't forget to finish the current activity.
#Override
public void onBackPressed(){
startActivity( new Intent(this, DashboardActivity.class) );
finish();
}

Crash when creating Activity

Good evening Stack !
I have started to learn Android development as a hobby and I am now trying to develop my first "real" application (I have made already only five simple applications from books).
In this application, I have two buttons that will "create" the same Activity but by using two different objects from the same base class, hence allowing me to customize the behavior of the application depending on the button that was clicked.
However, when I am trying to create the Intent instance, my application crashes.
Here is the code of the base Activity class
public class BaseDictionnaryActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.basedictionnary);
}
public void onDestroy()
{
super.onDestroy();
}
}
and here is the code that crashes. The line is the one creating the Intent object.
public class DictionnaryActivity extends Activity
{
private BaseDictionnaryActivity jlpt1;
private BaseDictionnaryActivity jlpt2;
private Button btjlpt1 = null;
private Button btjlpt2 = null;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dictionnary);
jlpt2 = new BaseDictionnaryActivity();
jlpt1 = new BaseDictionnaryActivity();
btJLPT1 = (Button)findViewById(R.id.jlpt1);
btJLPT1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt1.getClass());
jlpt1.this.startActivity(myIntent);
}
});
btJLPT2 = (Button)findViewById(R.id.jlpt2);
btJLPT2.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt2.getClass());
jlpt2.this.startActivity(myIntent);
}
});
}
public void onDestroy()
{
super.onDestroy();
}
}
Thank you for your help !
Just to make correction,
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt1.getClass());
In this the second argument must be, your target activity BaseDictionnaryActivity.class
So, it looks something like,
Intent myIntent = new Intent(DictionnaryActivity.this,
BaseDictionnaryActivity.class);
startActivity(myIntent);
Also please make sure there will be entry of BaseDictionnaryActivity in your Application's manifest file,
Which is look like,
<activity android:name=".BaseDictionnaryActivity"
....>
</activity>
Maybe:
Intent myIntent = new Intent(DictionnaryActivity.this,
BaseDictionnaryActivity.class);
startActivity(myIntent);
change this
Intent myIntent = new Intent(DictionnaryActivity.this,
NextActivity.class);
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt2.class);
^^^^^^^^^^^^
You need to provide next activity .class in second argument of Intent.
Replace jlpt1.getClass() with NameOfClassToBeLaunched.class
Also this is bad practice to create Activity instances in other activities.

Categories

Resources