I do my android app , but I have a bug I don't know how to fix it.
My code is below :
This is my Main Activity :
public class MainActivity extends Activity {
private ImageView imgHot;
public final static String EXTRA_MESSAGE="com.cuonglm.KhoHinh.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgHot=(ImageView)findViewById(R.id.imageViewHot);
imgHot.setOnClickListener(toContentHot);
}
View.OnClickListener toContentHot=new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent content=new Intent(MainActivity.this,ContentActivity.class);
String signal="1";
content.putExtra(EXTRA_MESSAGE,signal);
startActivity(content);
}
};
And this is my second Activity :
public class ContentActivity extends Activity {
private TextView viewMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent content=getIntent();
String messageReceive=content.getStringExtra(MainActivity.EXTRA_MESSAGE);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
setContentView(R.layout.activity_content);
}
I want to click on the image on the Main Activity , string "1" or number "1" will send to the Second Activity via Intent and view on the TextView.
But my app will be close "Unfortunately..."
Thanks
Change to
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
In your ContentActivity
findViewById looks for a view with the id for the current infalted layout. SO you need to set the content of your layout to the activity first and then initialize your views.
You are probably gettting NullPointerException coz your initialization fails.
You need to call setContentView() in your second Activity before trying to access any of the Views in that layout. Change it to
public class ContentActivity extends Activity {
private TextView viewMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
Intent content=getIntent();
String messageReceive=content.getStringExtra(MainActivity.EXTRA_MESSAGE);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
}
If this doesn't fix your problem then please post your logcat so we can see the error. Also always post logcat in the future when your app crashes. They aren't always this easy to see.
Also, I'm not sure you understand how putExtra() works. It is a key, value pair so when you put EXTRA_MESSAGE as the key then that is what you would use to retrieve the value added in the second param. So the way you are doing it may work if the Activity gets destroyed but it looks really strange to me and probably not realy safe or efficient. I would change it to something like
content.putExtra("message",signal);
in your first Activity then get it with
String messageReceive = content.getStringExtra("message");
in your second Activity
You need to set the layout before trying to reference the Views associated with it.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent content=getIntent();
String messageReceive=content.getStringExtra(MainActivity.EXTRA_MESSAGE);
setContentView(R.layout.activity_content);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
}
Related
I was developing an exam score calculator app.
When I want to call AD methods,advertisements don't show up.
Calculation process happens in OnCreate method:
public class resultActivity extends AppCompatActivity {
public String responseId;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
/*Calculation...*/}
and other voids like:
public void requestAd() {
/*AD RQUESTING PROCESS...*/
}
and
public void showAd() {
/*AD SHOWING PROCESS...*/
}
AD team gave me this code to call the method and it works well:
requestButton.setOnClickListener(v -> requestAd());
showButton.setOnClickListener(v -> showAd());
But the Problem is I don't have buttons to call them so I tried this:
public class resultActivity extends AppCompatActivity {
public String responseId;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
requestAd();
showAd();
/*Calculation...*/}
But when the activity starts ads don't show up!
The whole question is I want this methods to be called while this activity starts.
thank you.
Try building up the release version APK and test on it. Maybe your Ad-provider have some restrictions in debug version?
I made another class and moved request Ad and showAd there. Then, I made an object and called the method through object.
I have to mention that I changed a minor thing in requestAd but the main job was done by the object.
Thank You All.
This question already has answers here:
NullPointerException with findViewById in variable definition
(1 answer)
findViewByID returns null
(33 answers)
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
Well i get a NullPointerException when i I call findViewById() to access a Button. I think I understand why I'm getting this error but there are some questions I have unsolved in my head.
Well I think I'm getting this error because I moved the findViewById() calls from inside the onCreate() method to class scope, outside of all the methods.
So now I'm initializing my Button's and EditText's outside the onCreate() method.
Well if I understand correctly, this is happening(Null error) cause the setContentView() method is called after the findViewById() method, so that's why it throws an Exception.
But what I don't understand is that I have done the same thing in my second activity and works well without any null exception. And I'm initializing my Buttons etc outside the onCreate() method!
It does confuse me a little bit. Any help clearing this in my head would be much appreciated.
First Activity
public class FirstActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
private Button loginButton = findViewById(R.id.lo_loginButton);
private EditText username= findViewById(R.id.lo_usernameText);
private EditText password= findViewById(R.id.lo_passwordText);
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_login);
Log.i(TAG,"Create "+formatter.format(new Date()));
//listeners
signUpButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(LoginActivity.this, SignUpActivity.class));
finish();
}
});
}
Second Activity
public class SecondActivity extends AppCompatActivity {
private EditText username = findViewById(R.id.su_username);
private EditText password = findViewById(R.id.su_password);
private TextView errorText= findViewById(R.id.su_error_msg);
private Button signUpButton=findViewById(R.id.su_signupButton);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup);
Log.i(TAG,"Create");
//listeners
Button backButton = findViewById(R.id.su_backButton);
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(SignUpActivity.this, LoginActivity.class));
Log.i(TAG,"Going Back ");
finish();
}
});
You can't use this initialization:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
//....
}
Use:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup)
signUpButton= findViewById(R.id.lo_signUpButton);
//...
}
}
In the 2nd Activity you are doing something different:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
Button backButton = findViewById(R.id.su_backButton);
//...
}
and it is correct since you declaring and initializing the backButton with the findViewById method inside the onCreate after the setContentView call.
In the 1st Activity you are setting the listener with signUpButton.setOnClickListener but the signUpButton is not initialized (since it is outside the onCreate method)
Also in the 2nd Activity the other buttons that are wrongly initialized are not used in the OnCreate method.
In second activity, you have not used the buttons that are wrongly initialized, once you use them, it will cause exception too.
You have used backButton which is correctly initialized.
The answer is quite simple. the global variables get initialized before setContentView() is called, meaning what findViewById() will return null. findViewById() returns the view if found or null. As you didn't call setContentView yet, it cannot find the view you want.
The global variables in FirstActivity as well as SecondActivity are all null.
The difference between FirstActivity and SecondActivity is, that you don't access any global variable in SecondActivity.
The only view you used in SecondActivity is backButton, which you retrieved after calling setContentView, so of course, no NullPointerException will be thrown.
Always declare the variable as globally and initialize it in onCreate(). Even better, try to avoid global variables and pass them though method parameters.
I need to execute a method before initiating the layout in an activity. If I call the method I need to execute inside onCreate(), would it be executed before the layout is set?
The reason is because I need the method to return a piece of information that is displayed in the layout before initiating it. Would love some feedback on this.
You can do whatever you like before setContentView like so:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int i = 0;
setContentView(R.layout.main);
}
}
As long as you do not interact with views that have not been inflated yet
For example this is an error:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ERROR, CAN'T TOUCH UI ELEMENTS
ImageView img = (ImageView)findViewById(R.id.img);
setContentView(R.layout.main);
}
}
Default activity created with Android Studio contains following code
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Here is code, that executed before layout inflated
setContentView(R.layout.example_activity); //This line inflates layout
}
BTW, you can even remove setContentView and inflate layout programmaticaly.
Do it in onCreate(), preferably before calling setContentView().
However, if the data you want to receive comes from the network, then it will be obtained on a separate Thread (as no network calls can be done on the main Thread). In this situation the layout will almost certainly display before the data is obtained.
A solution would be to obtain the piece of data before you start the Activity, pass it in the Intent as extra and then retrieve in onCreate() using getIntent().getStringExtra()
You are probably inflating your layout in Activity.onCreate() with setContentView(), so you need to put your function call in that method before the call to setContentView().
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
yourFunctionCallHere();
setContentView(R.layout.act_main);
}
I have my code defined the way below. There are two crucial activities. Activity (1) shows some images in a ViewFlipper. It uses methods to load desired image directly. The onOptionsItemSelected() method fetches data from a menu defined within linked XML layout R.layout.browse. The other method, displaySelectedFlag(), gets a tag parameter passed from a different activity, let's call it activity (2).
Activity (1):
public class BrowserActivity extends AppCompatActivity implements SimpleGestureListener, View.OnClickListener {
public ViewFlipper vFlipper;
(...)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.browse);
vFlipper = (ViewFlipper) findViewById(R.id.viewFlipperBrowser);
(...)
} // onCreate() ends here
// this method below works fine:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
vFlipper.setDisplayedChild(item.getOrder());
return true;
}
// and this one doesn't:
public void displaySelectedFlag(int orderTag) {
vFlipper.setDisplayedChild(orderTag); // crashes here
}
}
Activity (2):
public class ListActivity extends Activity implements View.OnClickListener {
private BrowserActivity browserActivity = new BrowserActivity();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
ImageButton imageA = (ImageButton) findViewById(R.id.img_a);
imageA.setOnClickListener(this);
ImageButton imageB = (ImageButton) findViewById(R.id.img_b);
imageB.setOnClickListener(this);
}
public void displayImageInfo(View view) {
String tagValue = (String) view.getTag();
int tagId = Integer.parseInt(tagValue);
Intent intent = new Intent(this, BrowserActivity.class);
startActivity(intent);
browserActivity.displaySelectedImage(imageId);
}
#Override
public void onClick(View view) {
displayImageInfo(view);
}
}
As I checked, the method onClick() called in activity (2) fetches an ID of an ImageButton and passes it to activity (1). Unfortunately, I get a NullPointerException when calling the ViewFlipper (the line is marked in the code above, activity (1)).
Any idea why it happens?
You cannot reference one Activity from another activity. You must let the Android OS create the Activity object via the call to "startActivity". Allocating a local variable as an instance of an Activity doesn't actually mean anything (like your instantiation of the BrowserActivity). Apoorv's comment links to a decent article on the subject.
If you want to pass data from one Activity to another, you need to pass extras within the Intent's bundle. This post goes into detail: https://stackoverflow.com/a/819427/504252
I want to use a button click to pass selection parameters to another class that will build a map screen using the passed parameters. I am focused on getting my button action working. I a using onCLickListener and onCLickView as follows
Class1:
public class Class1 extends Activity implements OnClickListener {
Class2 class2;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
..........
Button button = (Button)findViewById(R.id.btn_configup1);
button.setOnClickListener(this);
}
public void onClick(View v) {
Class2 class2 = new Class2();
//Save state.. selections and params and use bundle
//to pass into class2
class2.execMapBuild();
}
}
Class2:
public class Class2 extends MapActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.drawable.navup);
}
public void execMapBuild() {
finish(); //just in case we return.
Intent intent = new Intent(CLass2.this, Class2.class);
startActivity(intent);
}
I have everything working except the desired button action. I want the button click in Class1.onVlickView to call Class2.execMapBuild using the button click action. I have the button click capturing the action and calling the execMapBuild method on Class2. But I get a NullPointerException as it moves from startActivity(intent) into onCreate.
I have tried several other ways of nailing this down, but this seems the best and I seem close to figuring it out. I would really appreciate an explanation of what I may be missing.
Added code that was initially not copied in.
To expand on #Heiko Rupp's answer, if you want Class2 to display a map, it needs to extend something like Activity. As such, you can't just call it with a normal method. You need to register the Activity in your manifest and then call it using an Intent. Here is a sample of the kind of thing you should be doing:
public class Class1 extends Activity implements OnClickListener {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Button button = (Button)findViewById(R.id.btn_configup1);
button.setOnClickListener(this);
}
public void onClick(View v) {
Intent intent = new Intent(Class1.this,Class2.class);
intent.putExtra("key","data");
...
startActivity(intent);
}
}
public class Class2 extends MapActivity {
String mData;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Bundle extras = getIntent().getExtras();
if (extras != null) {
mData = extras.getString("key");
...
}
...
}
}
Can I also suggest that you use more descriptive class names than Class1 and Class2.
Class2 is no activity, so the callbacks of an Activity will not be called by the system.
And if it were an Activity, you could not just call into it via new Class2(), as still the callbacks are not executed.
Try to clean this up and then start Class2 activity from Class1 with an Intent as you are doing within execMapBuild().