Back button throws NullPointerException [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I have a flow that goes MainActivity -> StoriesActivity -> StoryBodyActivity.
Each passes variables to the next using Intents.
I'm trying to implement a back button from StoryBodyActivity to StoriesActivity, but it's throwing a NullPointerException on authorID = extras.getInt("author_id"); in StoriesActivity.
I know what a NullPointer is. I just don't know how to fix this one! Could it be because it no longer has access to the data that was passed from the MainActivity?
Note: This works fine when clicking the back button on the device, just not the icon on the ActionBar.
Snippet from StoryBodyActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_story_body);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
Snippet from StoriesActivity:
private int authorID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stories);
Bundle extras = getIntent().getExtras();
authorID = extras.getInt("author_id"); // NullPointerException here
final String authorName = extras.getString("author_name");
Log.i("click", Integer.toString(authorID));
}
Snippet from MainActivity:
Intent intent = new Intent(MainActivity.this, StoriesActivity.class);
intent.putExtra("author_id", author.getID());
intent.putExtra("author_name", author.getName());
startActivity(intent);
Snippet from AndroidManifest:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity" android:theme="#style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".StoriesActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".StoryBodyActivity"
android:theme="#style/AppTheme"
android:parentActivityName="com.example.apple.bookshelf.StoriesActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.apple.bookshelf.StoriesActivity" />
</activity>
</application>

The problem you are facing is because of the line: 'android:parentActivityName="com.example.apple.bookshelf.StoriesActivity"'
When you are pressing the custom back button, it is creating a new instance of StoriesActivity. I'll suggest to remove:
android:parentActivityName="com.example.apple.bookshelf.StoriesActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.apple.bookshelf.StoriesActivity" />
And replace
NavUtils.navigateUpFromSameTask(this);
with
onBackPressed();

You have two solutions here:
First is to check if extras exists:
if(extras != null){
authorID = extras.getInt("author_id"); // NullPointerException here
final String authorName = extras.getString("author_name");
Log.i("click", Integer.toString(authorID));
}
Second solution is to use finish() instead of NavUtils.navigateUpFromSameTask(this); in StoryBodyActivity.
Hope it helps :)

To prevent this you can check if extra exists when coming to this activity.
if (getIntent().hasExtra("author_id")){
authorID = getIntent().getIntExtra("author_id",0);
}

try this way
SharedPreferences sharedPref1 = getSharedPreferences("alldetais", Context.MODE_PRIVATE);
SharedPreferences.Editor editor1 = sharedPref1.edit();
editor1.putString("author_id", author.getID());
editor1.putString("author_name", author.getName())
editor1.commit();
and get this way
SharedPreferences sharedPref1 = getApplicationContext().getSharedPreferences("alldetais", Context.MODE_PRIVATE);
author_id=sharedPref1.getString("author_id","");

I didn't see your code, but I can give an advice, you have to go with the flow of the activities, visualize it as follows,
Activity A -> activity B -> activity C
So now, if you want to pass data using intent from A to C, then you have to send the data from A to B, then receive it in B, then again pass the received data in from B to C and then use it. Also, i think the more correct way of getting data in B from A will be
Intent intent = getIntent();
intent.getExtras();

Related

Broadcast receiver - send String between apps

I am trying to send string from app to app.
First app called "send" has only "MainActivity" class and layout:
private void sendMsg(){
final TextView msg = (TextView) findViewById(R.id.sendText);
Button snd = (Button)findViewById(R.id.sendButton);
snd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!msg.getText().toString().trim().equals("")){
Intent intent = new Intent("Updated");
intent.setAction(Intent.ACTION_SEND);
intent.putExtra("TEXT", msg.getText().toString().trim());
intent.setType("text/plain");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent(new ComponentName("com.example.rec","com.example.rec.broadcastReciver"));
getApplicationContext().sendBroadcast(intent);
}else{
Toast.makeText(getApplicationContext(), "Write text that You want to broadcast!", Toast.LENGTH_LONG).show();
}
}
});
}
Second app called "rec" has two classes "broadcastReciver" and "MainActivity".
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
zoviBroadCast();
}
private void zoviBroadCast(){
broadcastReciver brcv = new broadcastReciver();
registerReceiver(brcv,
new IntentFilter("action"));
}
}
broadcastReciver:
public class broadcastReciver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent)
{
//String data = intent.getStringExtra("TEXT").trim();
if (intent != null)
{
String sIntentAction = intent.getAction();
if (sIntentAction != null && sIntentAction.equals("action"))
{
String data = intent.getStringExtra("TEXT").trim();
Toast.makeText(context, data, Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(context,"Something went wrong",Toast.LENGTH_SHORT).show();
}
}
}
}
I also added lines between tag "receiver" in "AndroidManifest.xml":
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rec">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".broadcastReciver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="action" />
</intent-filter>
</receiver>
</application>
</manifest>
What application should do is when I type something in first application and send it another over button it should "broadcast" (show) toast at second app.
My second application is not showing any data when run.
Nowadays it is essential to specify an action in intent filter of your broadcast receiver.
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_ACTION">
</action>
</intent-filter>
</receiver>
When sending the broadcast, you need to set exactly the same action to the intent you send.
Intent i = new Intent();
i.setAction("android.intent.action.MY_ACTION");
context.sendBroadcast(i);
Notation of action name may be not very important to get your code working, but I recommend to give names related to the package of your sending app.
For example: "com.username.example.myApplication.ACTION_EXAMPLE"

NavUtils navigateUpFromSameTask() and onSaveInstanceState()

I'm new to android development and I'm facing a problem.
I've got an activity, which contains a ListFragment. After the list item is tapped the new Activity starts. I decided to do a back Navigation in a child Activity with the Home button on the Menu bar.
if (NavUtils.getParentActivityName(getActivity()) != null){
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (NavUtils.getParentActivityName(getActivity()) != null){
NavUtils.navigateUpFromSameTask(getActivity());
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
And I also need to save the integer value into the parent Activity. So I override the onSaveInstanceState()
#Override
protected void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
Log.d("ACTIVITY_STATE", " onSave");
savedInstanceState.putInt(TAG_INT_VAL_SAVED, intVal);
}
But when I tap on the back arrow at the child Activity and the onCreate method of the parent Activity is called, it appears that the parameter Bundle is null, up to the Log of the following code...
if (savedInstanceState != null){
intVal = savedInstanceState.getInt(TAG_INT_VAL_SAVED);
Log.d("ACTIVITY_STATE", " onSave getting data"); // Never appears at LogCat
} else {
// code to assign intVal as if the Activity was just started
}
I'm a little confused, so I'd like to ask you, guys, for a help. Could you please tell, what's going on, when the navigation happens? And what should I do, to keep the intVal saved? Thank you!
B.t.w. It works fine on the screen rotation - the value is successfully retrieved.
The manifest looks like:
<activity
android:name=".ListItemActivity"
android:label="#string/app_name" >
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value=".MyListActivity"/>
</activity>
<activity android:name=".MyListActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

NFC app crashing on enableForegroundDispatch

I am trying to get NFC foreground dispatch to work in my app using the tutorials
here and here. From what I can deduce all other functions seem to be working a it is just the NFC forground dispatch system that isn't working.
In my onCreate, I check NFC exists and initialise pending Intents and filters and get the NFC adapter:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set some stuff
mTV = (TextView) findViewById(R.id.textView);
mButt = (Button) findViewById(R.id.button);
//mNfcAd = NfcAdapter.getDefaultAdapter(this);
//Init elsewhere
getAdapter();
//Hide button until its needed
mButt.setVisibility(View.INVISIBLE);
//Make sure NFC actually exists.....
if (mNfcAd == null) {
//Not going to work without NFC
Toast.makeText(this, "This device does not support NFC\nGet used to the pen and paper for now :/", Toast.LENGTH_LONG).show();
finish();
return;
}
Intent nfcIntent = new Intent(this, getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
nfcPendingIntent =
PendingIntent.getActivity(this, 0, nfcIntent, 0);
IntentFilter tagIntentFilter =
new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
tagIntentFilter.addDataType("text/plain");
intentFiltersArray = new IntentFilter[]{tagIntentFilter};
}
catch (Throwable t) {
t.printStackTrace();
}
//Init the prefs
initPrefs();
}
public void initPrefs() {
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
}
private NfcAdapter getAdapter(){
if(mNfcAd ==null){
NfcManager manager = (NfcManager) getSystemService(NFC_SERVICE);
mNfcAd = manager.getDefaultAdapter();
}
return mNfcAd;
}
I then go on to check NFC is enabled (if not display a button that shows NFC settings) as well as checking if the app is in its first run. At the end of onResume(), I (attempt to) enable Foreground Dispatch for the adapter.
protected void onResume() {
super.onResume();
//Define the mButt action
mButt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent dialogIntent = new Intent(Settings.ACTION_NFC_SETTINGS);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dialogIntent);
}
});
//If NFC exists, check if its turned on
if (!mNfcAd.isEnabled()) {
Toast.makeText(this, "You have NFC, but you haven't enabled it...", Toast.LENGTH_LONG).show();
mTV.setText("NFC not enabled");
mButt.setVisibility(View.VISIBLE);
}
//Check if first run
if (prefs.getInt("firstTime", 1) == 1 ||
prefs.getString("fullName", null) == null ||
prefs.getString("house", null) == null) {
Intent intent = new Intent(this, First_Run.class);
startActivity(intent);
prefs.edit().putInt("firstTime", 0);
prefs.edit().putString("fullName", getIntent().getExtras().getString("fullName"));
prefs.edit().putString("house", getIntent().getExtras().getString("house"));
prefs.edit().apply();
}
getAdapter().enableForegroundDispatch(this, nfcPendingIntent, intentFiltersArray, null);
handleIntent(getIntent());
}
The error is:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.nfc.NfcAdapter.enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][])' on a null object reference
However, all the arguments seem to be initialised;
It is being called in onResume, so the activity context is created;
nfcPendingIntent and intentFiltersArray are initialised in onCreate;
I do not have a techlist so I use null as the final argument;
The adapter itself is initialised in getAdapter.
I am currently combing through other tutorials to see the different methods that can be used, however I would really like to get this fixed.
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-permission android:name="android.permission.NFC" />
<application
android:fullBackupContent="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".First_Run"
android:label="#string/title_activity_first__run">
</activity>
</application>
Try creating your NfcAdapter object like below.
NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

Intent issue (display new form) Android

Ok I've been looking around for hours. I've tried just about everything and I'm not sure what is going on but I'm getting the issue where it can't find the activity. The activity is in my manifest file. I've tried with .ActivityName and com...ActivityName. I've saved, I've cleaned, I've closed/opened eclipse. It just can't seem to find it. Here's code, maybe I'm missing something?
Manifest file:
<activity android:name=".Activity2"></activity>
Listener in MainActivity:
View.OnClickListener test = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Activity2.class);
startActivity(intent);
}
};
Activity2:
public class Activity2 extends Activity {
ImageButton btnTest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO Auto-generated method stub
btnTest= (ImageButton)findViewById(R.id.btnDepressed);
btnTest.setOnClickListener(GoTest);
}
...etc.
I've read so many articles on this from here and other sites. I've watched videos.. I simply don't see what I'm doing wrong. The activity is defined in the manifest, I've tried the intent with the above code, as well as with:
new Intent("com.blah.blah.Activity2");
Neither is working. Any ideas?
try this
<activity android:name=".Activity2"
android:label="#string/app_name">
<intent-filter>
<action android:name="com.blah.blah.Activity2" />
</intent-filter>
</activity>
from activity code you have to do some thing like this
Intent intent = new Intent();
intent.setAction("com.blah.blah.Activity2");
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);`
Check your package com.blah.blah for Activity2.
Inside your AndroidManifest.xml you should define your package as:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blah.blah"
...
And define your activity as:
<activity
android:name="com.blah.blah.Activity2">
</activity>
OR
<activity
android:name=".Activity2">
</activity>

Can't switch between activities

sorry for asking dumb questions, java and Android are both new to me ;)
My problem: I can't switch between two activities in a very simple app. I tried solutions described in similar topics but it didn't work.
So this is my 1st Activity (I didn't paste the imports):
public class OneActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void OnStart(){
Button Btn = (Button)findViewById(R.id.btnNext);
Btn.setOnClickListener(new OnClickListener() {
public void onClick(View Button) {
Intent myIntent = new Intent(OneActivity.this, UserInput.class);
OneActivity.this.startActivity(myIntent);
}
});
}
}
The second Activity is very simple - it is just supposed to load a layout called userinput.xml:
public class UserInput extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.userinput);
}
}
The application part of the Manifest looks like following:
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".OneActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<activity
android:name=".UserInput"
android:label="#string/app_name" />
</activity>
</application>
When I run the app and click the button nothing happens. Where could be the problem?
// Alright, I have put the code into the onCreate() method so it now looks like following:
public class OneActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button Btn = (Button)findViewById(R.id.btnNext);
Btn.setOnClickListener(new OnClickListener() {
public void onClick(View Button) {
Intent myIntent = new Intent(OneActivity.this, UserInput.class);
OneActivity.this.startActivity(myIntent);
}
});
}
}
Now the app crashes (force close) anytime I click the Next button.
You define your onStart() function with a capital 'O'. That is why the function is never called.
Your onStart():
public void OnStart(){ ... }
How it should be:
// Note the lowercase 'o' in onStart
public void onStart(){ ... }
Also note that having an #Override above the function name when you want to override a method will help prevent making these mistakes, as Eclipse (or whatever IDE you use) will tell you that you are not actually overriding a function.
Write below code in onCreate() method:
Button Btn = (Button)findViewById(R.id.btnNext);
Btn.setOnClickListener(new OnClickListener() {
public void onClick(View Button) {
Intent myIntent = new Intent(OneActivity.this, UserInput.class);
startActivity(myIntent);
}
});
2nd correction for android manifest file:
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".OneActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <!-- closed here -->
<activity
android:name=".UserInput"
android:label="#string/app_name" />
</application>
You can move all the code in onCreate() and simplify like this
startActivity(new Intent(this, UserInput.class));
But I don't understand why you start another activity like this
Check it following line
Intent myIntent = new Intent(OneAvtivity.this, SecondActivity.class);
startActivity(myIntent);
Your Class name is UserIpnout and you write SecondActivity.class
Intent myIntent = new Intent(OneAvtivity.this, UserInput .class);
startActivity(myIntent);

Categories