when i press back arrow in toolbar getting a null object reference - android

I am trying to my send data from second activity to third activity it working
fine when I click back arrow in tool back I am getting this error please any one help me how to resolve this one
here my second activity code
pos=Integer.parseInt((getIntent().getExtras()).getString("pos"));
webviewurl=NewsMainFregmant_List.listData.get(pos).getNewsSourceUrl();
webviewurl2=NewsMainFregmant_List.listData.get(pos).getNewsSourceUrl2();
news_site_link_one=(TextView)findViewById(R.id.news_SourceLink_text_one_t_webview);
news_site_like_two= (TextView)findViewById(R.id.news_SourceLink_text_two_t_webview);
news_site_link_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent webviewintent = new Intent(getApplicationContext(), News_WebView.class);
webviewintent.putExtra("webviewurl", webviewurl);
startActivity(webviewintent);
}
});
here below my webview
String SourceURL;
WebView webview;
final Activity activity = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_news__web_view);
Intent intent =getIntent();
SourceURL = intent.getStringExtra("webviewurl");
webview=(WebView)findViewById(R.id.webView);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress)
{
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if(progress == 100)
activity.setTitle(R.string.app_name);
}
});
webview.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// Handle the error
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
webview.loadUrl(SourceURL);
}
#Override
public void onBackPressed() {
if (webview.canGoBack()) {
webview.goBack();
} else {
super.onBackPressed();
overridePendingTransition(R.transition.slide_in_down, R.transition.slide_out_down);
}
}
Here below my error code
Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference

It means that this line :
pos=Integer.parseInt((getIntent().getExtras()).getString("pos"));
points to nothing, getString("pos") does not exist.
There can be many reasons for that. Probably your not filling the intent with Extras when you press back in your Toolbar.
You can do a null check :
if(getIntent().getExtras() != null)
pos=Integer.parseInt((getIntent().getExtras()).getString("pos"));
But better take care of it in your Toolbar back ClickListener and make sure it is not null.
By the way :
Integer.parseInt((getIntent().getExtras()).getString("pos"))
is not good practice. If you want to get a single Integer from an intent you use :
getIntent().getIntExtra("pos", 0); // will be 0 if null
You put it in the intent extra like this :
intent.putExtra("pos", 666);
Now your intent Extra "pos" is assigned the value 666.

It looks like error is in below line
pos=Integer.parseInt((getIntent().getExtras()).getString("pos"));
So you can do 2 things here.
Method1
if(getIntent().getExtras() != null)
pos=Integer.parseInt((getIntent().getExtras()).getString("pos"));
or
Method2
Change your back pressed method
#Override
public void onBackPressed()
{
if (webview.canGoBack())
{
webview.goBack();
} else {
Intent backIntent = new Intent(getApplicationContext(), PreviousClass.class);
backIntent.putExtra("pos",pos);
startActivity(webviewintent);
overridePendingTransition(R.transition.slide_in_down, R.transition.slide_out_down);
}
}
but for this u need to pass pos variable on moving from second activity to third also.

According to the Android reference guide, getExtras():
returns the map of all extras previously added with putExtra(), or null if none have been added.
So it looks like you never called putExtra() or didn't use it correctly.

Related

Put And Get Extras From Another Class

I have Act_01 (where I put value) and Act_02 (where I get value) but have declared these methods in a Extras class, getting value from Act_02 returns null value:
Act_01: (Where I want to pass the value Name to Act_02)
public class Act_01 extends Activity {
Extras cc_Extras;
Button btn1;
Intent intent;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_01);
cc_Extras = new Extras();
str_Name = "Buck";
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cc_Extras.putExtras();
startActivity(intent);
}
});
}
}
Act_02: (Where I want ot receive value Name from Act_01 but the app crashes with null value)
public class Act_02 extends Activity {
Extras cc_Extras;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_02);
cc_Extras = new Extras();
if(getIntent() != null && getIntent().getExtras() != null)
{
cc_Extras.getExtras();
}
Toast.makeText(getApplicationContext(), "Name: "+str_Name, Toast.LENGTH_SHORT).show();
}
}
Extras: (Where I define the methods to put and get Extras)
public class Extras extends Activity {
String str_Name;
Intent intent;
public void putExtras() {
// TODO Auto-generated method stub
intent.putExtra("KEY_Name", str_Name);
}
public void getExtras() {
// TODO Auto-generated method stub
str_Name = getIntent().getExtras().getString("KEY_Name");
}
}
EDIT: I do not want to pass and get data directly between activities, I want to use the 3rd class (Extras.java) because I have too many activities having too many values between each other and want to sort of define them globally in Extras so that all my other activities can just call one method instead of getting and putting too many values in my activities.
Your app crashes not with a null value, but a null pointer reference because you created a new Activity manually
cc_Extras = new Extras();
Then called a lifecycle method on it
cc_Extras.getExtras()
Which calls getIntent(), but the Intent was never setup by the Android framework, and cc_Extras.getExtras() wouldn't have any of the data you wanted anyway in the second Activity because it was just created there, not from the first Activity.
Briefly, you should never make a new Activity, and your Extras class does not need to be an Activity in the first place (nor does it provide much benefit).
Just use the Intent object provided by the first Activity to start the second Activity, and get extras like normal. Don't overcomplicate your code. Regarding the title of the question, Intent and Bundle are already "another class" designed by Android for you to transfer data.
On both activities you are creating a new instances of Extras class means they dont hold the same value you can do this to transfer data from A to B
public class Act_01 extends Activity {
Button btn1;
Intent intent;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_01);
str_Name = "Buck";
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
intent = new Intent(Act_01.this, Act_02.class);
intent.putExtra("data", str_Name)
startActivity(intent);
}
});
}
}
And receieve data like this
public class Act_02 extends Activity {
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_02);
// cc_Extras = new Extras();
if(getIntent() != null)
{
if (getIntent().getStringExtra("data") != null) {
Toast.makeText(Act_02.this, "Name: "+getIntent.getStringExtra("data"), Toast.LENGTH_SHORT).show();
}
}
}
}
Also you should consider using Activity Context instead of the application context
Ok! so here are the few things I might wanna suggest you to correct.
Changes needs to be done in the code.
You are not assigning anything to "intent" object , and you have passed a intent without assigning anything to it.
Your instance cc_Extra isn't doing anything in the activity1. You might wanna pass the "intent" object in your constructor of class like cc_Extras= new Extras(intent); and in the Extras class do the following- Intent intent;
Extras(Intent i)
{
this.intent=i;
}
In the activity2 you are creating the new Instance of Extras(). So according to your code it is going to be NULL by default. If you have done the changes from the previous step, you can create new instance by doing cc_Extras(getIntent());
Corrections in the code
1) In Extras class getExtras() method instead of str=getIntent() use str=intent.getExtras.getString().
2) In the activity2 you are not assigning anything to your String str_Name, so you need to return the string you got in getExtras() method. You can do it by changing the return type to String. Below is the sample code.
public String getExtras()
{
str_Name=intent.getExtras().getString("KEY_Name");
//OR
//str_Name=intent.getStringExtra("KEY_Name");
return str_Name;
}
3) By the doing this you need to catch this string in the activity2 by doing `
if(getIntent() != null && getIntent().getExtras() != null)
{
str_Name=cc_Extras.getExtras();
}`
4) Another thing is you must create intent like this-
Intent intent=new Intent(currentActivityName.this,anotherActivity2.class);
//then use the intent object
EDIT- Your code must look like this in the end...
Act1
public class Act_01 extends Activity {
Extras cc_Extras=null;
Button btn1;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_01);
str_Name = "Buck";
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//changes to do
Intent intent= new Intent(Act01.this,Act02.class);
cc_Extras= new Extras(intent);
cc_Extras.putExtras(str_Name);
//end
startActivity(intent);
}
});
}
}
Act02
public class Act_02 extends Activity {
Extras cc_Extras;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_02);
cc_Extras = new Extras(getIntent());
if(getIntent() != null && getIntent().getExtras() != null)
{
str_Name=cc_Extras.getExtras();
}
Toast.makeText(getApplicationContext(), "Name: "+str_Name, Toast.LENGTH_SHORT).show();
}
}
Extras class
public class Extras { //remove "extends Activity" because it is a class not a activity
String str_Name;
Intent intent;
Extras(Intent i)
{
this.intent=i;
}
public void putExtras(String str) {
// TODO Auto-generated method stub
str_Name=str;
intent.putExtra("KEY_Name", str_Name);
}
public String getExtras() {
// TODO Auto-generated method stub
str_Name = intent.getExtras().getString("KEY_Name");
return str_Name;
}
}
Above code will work just on String. You can extend the functionality if you want.
I hope this must work to get your code working!

how to override onBackPressed inside an if statement?

My aim is to override the code of my onBackPressed method..
I have overridden the onBackPressed inside my activity
#Override
public void onBackPressed() {
this.finish();
}
The code below is inside onCreate(), how can i override the onBackPressed to do something like go to another intent instead,
if(mode.equals("edit")){
//onBackPressed();
}
EDIT!!
sorry for unclear question,
What i want to know is, is there a way to override the method inside to onCreate method's if statement?
Just do this:
#Override
public void onBackPressed() {
// Check your mode in onBackPressed
if(mode.equals("edit")){
// Launch the intent
Intent editIntent = new Intent(MyActivity.this, EditActivity.class);
startActivity(editIntent);
// else call to the super class method, for default behavior
}else{
super.onBackPressed();
}
}
There is nothing stopping you from making an onBackPressed call from any method in your Activity class:
public class MainActivity extends AppCompatActivity {
private int editMode = 1;
private String mode = "edit";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// This is totally legal to do
if(editMode == 1){
onBackPressed();
}
}
}
Since the method onBackPressed() is a public method You can do this:
inside onCreate(){
if(mode.equals("edit")){
onBackPressed();
}
else
Log.d("dj","something else");
}
in onBackPressed, i did this for testing:
#Override
public void onBackPressed() {
Log.d("dj", "Yeah! on back pressed");
//super.onBackPressed();
}
I think you want to perform some operation based on the calling location,
for that I think you can follow the given below method:
onCreate(){
if(Edit){
performOperation(EDIT_OPERATION);
}
if(View){
performOperation(VIEW_OPERATION);
}
}
onBackPressed(){
performOperation(BACKP_RESSED);
}
performOperation(int operationType){
/*
* do operation
*/
}
I hope this is what you want

onLoadFinished called when I click back button from othe Activity

I try to work with AsyncTaskLoader and I have one problem. I load in AsyncTaskLoader data from the internet then start other activity(BusModelsActivity) in method onLoadFinished
#Override
public void onLoadFinished(Loader<List<BusModelParcelable>> loader, List<BusModelParcelable> data) {
hideDialog();
Log.d("onLoadFinished", TestTags.TAG1);
Intent intent = new Intent(BusSearchParamActivity.this,BusModelsActivity.class);
intent.putParcelableArrayListExtra(AppVariables.BUS_MODELS_LIST, (ArrayList) data);
startActivity(intent);
}
but when I click back in activity BusModelsActivity and return to BusSearchParamActivity method onLoadFinished run again, and BusModelsActivity starts again. What to do with it? I call other activity when click at button:
public void pickUpButtonClick(View v) {
getSupportLoaderManager().initLoader(LOADER_MODELS,null,busModelsCallBack);
}
where busModelsCallBack is implementation of LoaderCallbacks interface. When I did debug it stoped only on onLoadFinished, not onCreateLoader or click button.
I am afraid to tell you that the AsyncTask behavior till now are not 100% granted. You have two ways to overcome this problem.
1)Do your actions in a Thread instead of AsyncTask. This will ensure that your code will be executed only once cause Thread never start twice until you want this. As following
new Thread(new Runnable() {
#Override
public void run() {
/All your code here
}
}).start();
2)Declare a static parameter in your activity called isPageLoaded initially with value false and set it to true inside your onLoadFinished after loading your page at the first time and check on its value before executing your onLoadFinished code as following:
#Override
public void onLoadFinished(Loader<List<BusModelParcelable>> loader, List<BusModelParcelable> data) {
if(!isPageLoaded){
hideDialog();
Log.d("onLoadFinished", TestTags.TAG1);
Intent intent = new Intent(BusSearchParamActivity.this,BusModelsActivity.class);
intent.putParcelableArrayListExtra(AppVariables.BUS_MODELS_LIST, (ArrayList) data);
startActivity(intent);
isPageLoaded = true;
}
}
Try:
private static boolean isClicked = false;
#Override
public void onLoadFinished(Loader<List<BusModelParcelable>> loader, List<BusModelParcelable> data) {
if(isClicked )
{
hideDialog();
Log.d("onLoadFinished", TestTags.TAG1);
Intent intent = new Intent(BusSearchParamActivity.this,BusModelsActivity.class);
intent.putParcelableArrayListExtra(AppVariables.BUS_MODELS_LIST, (ArrayList) data);
startActivity(intent);
isClicked = false;
}
}
public void pickUpButtonClick(View v) {
isClicked = true;
getSupportLoaderManager().initLoader(LOADER_MODELS,null,busModelsCallBack);
}

Progress bar with AsyncTask Object on initial app load

I have looked around on the API and through a few questions on here, and I think I am on the right path. My app is based on a webView object and the initial load has quite a few cached pages so I want progressDialog on the initial start up instead of the blank black screen. Right now the app just crashes but I believe it is because I am creating and calling the AsyncTask object in the wrong place. Right now it is being called in the onCreate() method. I’m not new to Java but I am new to Android and this idea of not working with a main() function is confusing to me.
So where should I call the execute() function if I only want the ProgressDialog shown on the initial launch? And is my AsyncTask object even set up correctly?
public class site extends Activity {
private WebView engine;
private String urlSave;
private WebViewClient yourWebClient;
private ProgressDialog initLoadDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
yourWebClient = new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("tel:") == true) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
}
else if(url.contains(“blah") == true && url.contains(“blah2") == false) {
view.loadUrl(url);
}
else if(url.contains(“blah3") == true) {
double[] loc = getGPS();
url += "&cLat=" + loc[0] + "&cLong=" + loc[1];
view.loadUrl(url);
}
else {
/*Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("url"));
startActivity(browserIntent);*/
}
return true;
}
};
}
#Override
public void onStart() {
progressSetup();
setContentView(R.layout.main);
}
public void progressSetup () {
initLoadDialog = new ProgressDialog(site.this);
initLoadDialog.setMessage("A message");
initLoadDialog.setIndeterminate(false);
initLoadDialog.setMax(100);
initLoadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
urlLoad loading = new urlLoad();
loading.execute();
}
private class urlLoad extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... url) {
try {
engine = (WebView) findViewById(R.id.web_engine);
engine.getSettings().setJavaScriptEnabled(true);
engine.getSettings().setBuiltInZoomControls(true);
engine.getSettings().setSupportZoom(true);
engine.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
engine.getSettings().setGeolocationEnabled(true);
engine.setWebViewClient(yourWebClient);
engine.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
engine.loadUrl(“albhal");
} catch (Exception e) {}
return null;
}
protected void onProgressUpdate(Integer... progress) {
initLoadDialog.setProgress(engine.getProgress());
}
}
}
Check your adb log, the error will pretty much explain to you what you didn't do right.
There's a lot of bad practice in your code. For example you call setContentView() in two Methods with different Layouts. The Flow of a android application is to call "onCreate", then "onStart". There is no reason to distinguish between those methods for you. Merge them and decide which layout to populate.
Also it is recommended to change the user-interface (this means also the dialogs) through the managing activity. In your case you are creating a ProgressDialog in the activity which then gets modified by the task. This is something you should avoid.

sharing "Global" variables across activities, problem when using a Webview...?

I'm sharing some variables accross activities by using a class like this :
public class Globals {
static Boolean hint1_graph_type_switcher;
static Boolean hint2_stockview_valuation;
other variables ...
}
then I'm using these variables anywhere across my multiple activites with ...
if (Globals.hint2_stockview_valuation == false) {
....
}
pretty basic and it was working fine untill ...
I introduced some webview stuff like this:
//-----------------------------------------------------------
// open a webview with the NEWS when the more_arrow is clicked :
mNews.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String news_URL = "http://us.m.yahoo.com/w/yfinance/symbolheadlines/"+ ticker + "/?.intl=us&.lang=en";
Intent news_Webview_intent = new Intent(Chart_View.this, News_Webview.class);
news_Webview_intent.putExtra("NEWS_URL", news_URL);
startActivity(news_Webview_intent);
}
});
//-----------------------------------------------------------
and here's the News_Webview.class:
public class News_Webview extends Activity {
//
// http://www.chrisdanielson.com/tag/progressdialog/
//
String news_URL;
private WebView webview;
private ProgressDialog progressBar;
private static final String TAG = "Hub";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.webview_news);
this.webview = (WebView)findViewById(R.id.webView);
Bundle extras = getIntent().getExtras();
if (this.getIntent().getExtras()!=null){
news_URL = extras.getString("NEWS_URL");
}
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
progressBar = ProgressDialog.show(News_Webview.this, "", "Loading...");
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//Log.i(TAG, "Processing webview url click...");
Intent viewIntent = new Intent("android.intent.action.VIEW", Uri.parse(url));
startActivity(viewIntent);
return true;
}
public void onPageFinished(WebView view, String url) {
//Log.i(TAG, "Finished loading URL: " +url);
if (progressBar.isShowing()) {
progressBar.dismiss();
}
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Log.e(TAG, "Error: " + description);
Toast.makeText(News_Webview.this, "Oh no! " + description, Toast.LENGTH_SHORT).show();
alertDialog.setTitle("Error");
alertDialog.setMessage(description);
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
});
webview.loadUrl(news_URL);
}
}
the problem now is that, when it "comes back" from this Activity, it looks like my Globals variables have disappeared ???
if (Globals.hint2_stockview_valuation == false) {
fires an error :
06-23 12:14:03.443:
ERROR/AndroidRuntime(2611): Caused by:
java.lang.NullPointerException
2 questions then :
Should I use something else than this "Global" class to share variables across activities ? Is it just bad practice to do this ?? I know that I can use the preferences but I thought it was quicker to do it this way (no need to "read" the preferences everytime I start a new activity ...
Any idea on WHY this is happening ? Should I "get back" my savedInstanceState in some way when my activity returns from the News_Webview.class ???
As always, thank you for your help.
H.
U could use intent.putExtra() for inter-activity interaction...
One thing(just for diagnostics) i would suggest is initializing the static variables to some value and then run the App... i suppose your global class is getting re-initialized when the intent started activity returns back...
I have used global variables, but in my case i kept them in an activity which never died. All other activities came after it and it worked perfectly fine...
The NullPointerException is bubbling up from the android runtime and has nothing to do with your Globals type.

Categories

Resources