I'm quite new to programming.
I'm trying to make a simple app with two activities, where the second activity can change the text of the first. I know it can be done using intents, but I was wondering if there is a more direct way of doing it, for example using the second activity to call a function from the first activity?
Here's the code I have so far:
The MainActivity, which contains a TextView and a button to open the second activity:
public class MainActivity extends Activity {
TextView textview;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.et2);
button = (Button) findViewById(R.id.b1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, ChangeText.class);
startActivity(intent);
}
});
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
public void changetext(String message) {
textview.setText(message);
}
}
And the second activity, ChangeText, which contains an EditText and a button which should change the text of the TextView in MainActivity and then finish itself:
public class ChangeText extends Activity{
EditText edittext;
Button button;
private MainActivity mainclass;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.change_text);
edittext = (EditText)findViewById(R.id.et2);
button = (Button)findViewById(R.id.b2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String message = edittext.getText().toString();
mainclass.changetext(message);
finish();
}
});
}
}
As you can see I tried to make the app work by making a public function in MainActivity which receives a string and sets the TextView with it, and then I call this function from the ChangeText activity.
The problem: it keeps crashing! Can anyone tell me how I can make this work?
Seems like I answered almost exactly the same question a week or so ago, so this is probably a duplicate, but I can't seem to find the original question.
The short answer is no - you can't call a method in an Activity from another Activity. The issue is that for normal programming purposes, only one Activity exists at a time*.
If you do something to circumvent this, then you're risking causing some major issues, including high memory usage, null pointer exceptions, etc.
The correct way to do this is indeed through the Intent system.
* Activities may or may not actually get destroyed when they become inactive, depending on things like how you use the back stack.
However, you should always program is if they do get destroyed when they become inactive - read, understand, and respect the Activity lifecycle.
For something as simple as your app, the "most direct" approach is to use the intent and startActivityForResult and them implement an onActivityResult in your main activity.
The problem you'll run into, even if you correctly pass you Activity references around is they are not guaranteed to be running at the same time.
Other ways aside from Intents, is to use a class(s) not involved with the Activity. Either a background service or a static variable in a class that extends Application. I rarely use Application classes anymore in favor of services and binding Activities them.
If I use an EventBus in projects, they can send Sticky events, which will hold the data until cleared.
Android uses a messaging mechanism to communicate between its components. This messaging mechnism is essential to Android, so you should use it. And as you already said, the messaging is implemented by Intents. ;-)
If you want something more complex, use an EventBus or implement a your own subscribe/publish mechanism that does what you want.
Use static variable
Example
In your MainActivity define
public static String msg = null;
then in your ChangeText activity assign changed text to it like
MainActivity.msg = edittext.getText().toString();
now in your main activity override the onResume() methode
if(msg != null){
textview.setText(msg);
msg = null;
}
You must LocalBroadCast Manager to do so
Here is the MainActivity which has the TextView which has to updated by another Activity
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView txt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt=(TextView)findViewById(R.id.txt1);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String s1= intent.getStringExtra("myString");
getIt(s1);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
public void getIt(String s)
{
System.out.println(s);
txt.setText(s);
}
public void go(View view)
{
Intent intent = new Intent(this,WriteText.class);
startActivity(intent);
}
}
And This is the Activity which contains the EditText which updates the TextView in the previous activity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
public class WriteText extends Activity {
EditText ed1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_text);
ed1 = (EditText)findViewById(R.id.textView);
}
public void come(View view){
Intent intent = new Intent("custom-event-name");
intent.putExtra("myString", ed1.getText().toString());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
This Worked for me , Hope it works for you too
Related
We are working on creating a basic app in my online class and I keep running into this issue where the Instructions have us type a method with an #Override for an onClick. I was able to get one of the methods to work with an autofill help from A.S. itself but this next one won't fix itself out. I have run into other issues over this class as well and I know the Instructions are a few years old. Possibly out of date now?
I'm pretty new to Android Java and coding overall. It seems that the app is trying to use the onClick method incorrectly. I will post the whole class I'm working with because I'm not sure where the problem is exactly.
package com.test.firstandroidapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
public class InformationPageActivity extends AppCompatActivity {
Button btnSave;
Spinner spnSeason;
SeekBar skbTemp;
TextView lblSeekValue;
Switch swchAllergy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_information_page);
spnSeason = (Spinner) findViewById(R.id.spnSeason);
skbTemp = (SeekBar) findViewById(R.id.skbTemp);
swchAllergy = (Switch) findViewById(R.id.swchAllergy);
lblSeekValue = (TextView) findViewById(R.id.lblSeekValue);
btnSave = (Button) findViewById(R.id.btnSave);
btnSave.setOnClickListener((View.OnClickListener) this);
skbTemp.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
String display = String.valueOf(progress);
lblSeekValue.setText(display);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
#Override
public void onClick(View v) {
String season, allergies;
int temperature;
season = spnSeason.getSelectedItem().toString();
temperature=skbTemp.getProgress();
allergies = (String) (swchAllergy.isChecked() ? swchAllergy.getTextOn() : swchAllergy.getTextOff()); //if the switch is on then the user has allergies
Intent intent = new Intent(InformationPageActivity.this, InformationResultsActivity.class); //pass information to the results activity
intent.putExtra("season", season);
intent.putExtra("temperature", temperature);
intent.putExtra("allergies", allergies);
this.startActivity(intent);
}
}
And here is the Main Menu Class parts that go to the view i'm trying to have opened, The onclicklistener is inside the onCreate method and the goInfo is it's own method
Button btnInfo = (Button) findViewById(R.id.btnInfo);
btnInfo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
goInfo();
}
}
);
}
private void goInfo() {
Intent intent = new Intent(MainMenuActivity.this, InformationPageActivity.class);
this.startActivity(intent);
}
I was able to find the issue. I needed to add an implements statement to the class for the onclicklistener. I'm answering my own question in case someone in the future has the same error. Here is what I did.
My problematic class was
public class InformationPageActivity extends AppCompatActivity {
This was causing the error "java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.firstandroidapp/com.test.firstandroidapp.InformationPageActivity}: java.lang.ClassCastException: com.test.firstandroidapp.InformationPageActivity cannot be cast to android.view.View$OnClickListener"
I solved the issue by fixing the class adding the implements
public class InformationPageActivity extends AppCompatActivity implements View.OnClickListener {
I am trying to access MainActivity function to my another java class. But i am not able to use these function. Please tell me what else need to be added to get it access.
My code:
Where i am trying to access my MainActivity
package com.example.musicplayer;
**import com.example.musicplayer.MainActivity;**
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class current_song extends Activity implements OnClickListener{
MainActivity ma = new MainActivity();
protected void onCreate(Bundle icicle) {
Bundle extra = getIntent().getExtras();
super.onCreate(icicle);
setContentView(R.layout.songplay_page);
if(extra != null){
String song_name = extra.getString("song_name");
TextView textchange = (TextView)findViewById(R.id.current_song_name);
textchange.setText(song_name);
textchange.setSelected(true);
}
Button btn_pause = (Button)findViewById(R.id.pause_btn);
btn_pause.setOnClickListener(this);
Button btn_next = (Button)findViewById(R.id.next_btn);
btn_next.setOnClickListener(this);
Button btn_prv = (Button)findViewById(R.id.prv_btn);
btn_prv.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "In Onclick ()", Toast.LENGTH_SHORT).show();
switch(v.getId())
{
case R.id.pause_btn:
Toast.makeText(getApplicationContext(), "pause", Toast.LENGTH_SHORT).show();
ma.pause();
break;
case R.id.next_btn:
ma.next();
break;
case R.id.prv_btn:
ma.prv();
break;
}
}
}
Make sure that MainActivity has a zero argument constructor and the access specifier for pause , next and prv function is public.
In response to "i have some methods defined by me stop(), next(), pri() i am trying to access these methods when i click on each button. If you think that "creating a separate common class for sharing all methods" can you please show me 1 example bec i don't know how to access a method from 1 activity to another. "
public class myController{
private MyActivity m;
public myController(MyActivity m){
this.m = m;
}
public void stop(){
m.stop;
}
}
In other classes you initialize in the main activity and pass it the controller object so it can call the stop method
Good day. I'm having some issues with my android project specifically listview. I tried searching for other information here in this site, and implemented some of the answers. However, it is still not working.
The error specifically is
NullPointerException at line 76 at MainActivity
Here is the code of my MainActivity
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
final ArrayList<String> studentName = new ArrayList<String>();
ArrayAdapter<String> aa;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView myList = (ListView) findViewById(R.id.listName);
aa = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, studentName);
myList.setAdapter(aa);
//droid.R.id.list;
//add
Button bAdd = (Button) findViewById(R.id.addstudent);
bAdd.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
startActivity(new Intent("android.intent.action.ADDSTUDENTS"));
}
});
//edit
Button bEdit = (Button) findViewById(R.id.editstudent);
bEdit.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View x) {
startActivity(new Intent("android.intent.action.EDITSTUDENTS"));
}
});
//edit
Button bDelete = (Button) findViewById(R.id.deletestudent);
bDelete.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View x) {
startActivity(new Intent("android.intent.action.DELETESTUDENTS"));
}
});
}
public ArrayList<String> getArray(){
return studentName;
}
public void notifyArray(){
aa.notifyDataSetChanged();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
and line 76 by the way is
aa.notifyDataSetChanged();
Here is my code for the AddStudents class
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class AddStudents extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.add_student);
Button bAddStudents = (Button) findViewById(R.id.add);
final EditText et = (EditText) findViewById(R.id.student_name);
bAddStudents.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
MainActivity as = new MainActivity();
as.getArray().add(et.getText().toString());
as.notifyArray();
finish();
}
});
Button bBack = (Button) findViewById(R.id.backadd);
bBack.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
finish();
}
});
}
}
and the xml part with the list view is
<ListView
android:id="#+id/listName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
</ListView>
I hope you can help me cause I want to also learn what my mistakes are. I can add other information if you want.
In your AddStudents class, you're calling notifyArray() right after you instantiated MainActivity. MainActivity.onCreate() will not be called just by instantiating it.
Instantiating your MainActivity there is probably not what you want anyway (because that object will be disposed directly after the onClick handler is done).
What you want instead is to access the existing instance of MainActivity. For that, add a reference to the current instance to a static member of your MainActivity class, e.g.
public class MainActivity extends Activity {
public static MainActivity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
activity = this;
}
}
Then in your AddStudent class access it via
MainActivity.activity.notifyArray()
This is not the most beautiful way to solve your issue, but it works as long as you can be sure to only have one MainActivity instance. (If not, you could make the array itself static; or create a Singleton wrapper class for it.)
notifyArray() is being called before onCreate.
Try calling getArray().add(et.getText().toString()); and notifyArray(); inside onResume() of MainActivity and NOT from AddStudentActivity( not recommended!)
So onResume() you would ideally want to add a new student to the list, so in your case, you can retrieve the student name using a common sharable object like a hashtable or somethiing similar, make it a singleton, and use it from anywhere in the applciation
The common class may go something like:
class CommonHashtable{
private static Hashtable<String, Object> commonHashtable = null;
public static getInstance(){
if(commonHashtable == null)
commonHashtable = new Hashtable<String, Object>();
return commonHashtable;
}
on getInstance(), it returns a commonHashtable which can be used to store values temporarily!
so, add this on addbutton click event
Hashtable hash = CommonHashtable.getInstance();
hash.put("NEW_STUDENT_NAME", et.getText().toString());
and add this in you onResume() of MainActivity
Hashtable hash = CommonHashtable.getInstance();
Object studentName = (String) hash.get("NEW_STUDENT_NAME");
if(studentName != null){
notifyArray();
}
I'm still getting, "The type OnDemandAndAutomatic_Activity must implement the inherited abstract method View.OnClickListener.onClick(View)"
even though I've implemented the method in two places (placed in both places via "Quick Fix").
This is my code:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class OnDemandAndAutomatic_Activity extends Activity implements View.OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ondemandandautomatic_activity);
// try commenting the button code out to see if that lets it run...
Button buttonAuthorizeUsers = (Button) findViewById(R.id.buttonAuthorizeUsers);
buttonAuthorizeUsers.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent configure = new Intent(OnDemandAndAutomatic_Activity.this, Configure_Activity.class);
OnDemandAndAutomatic_Activity.this.startActivity(configure);
}});
}
/* #Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent configure = new Intent(OnDemandAndAutomatic_Activity.this, Configure_Activity.class);
OnDemandAndAutomatic_Activity.this.startActivity(configure);
}*/
}
Since OnDemandAndAutomatic_Activity claims to implement View.OnClickListener, you need to have the onClick() implementation that you have commented out, otherwise it will not compile.
Also, you are separately presently creating an anonymous inner class instance of View.OnClickListener that you are passing to setOnClickListener(). It too will need an implementation of onClick().
If you are thinking that you should only need one of these, then either remove implements View.OnClickListener from your class declaration or pass this to setOnClickListener().
I've looked all over the place and taken all of the tips given, but my app still force closes.
The app has two classes (Main and Next) and "Next" class has a get method. When I try to use the get method in the "Main" class my app force closes. This is the line of code that causes the problems:
timesHit_txtview.setText(next.getTimesHit());
Like I mentioned before, I don't get any errors in eclipse. The First error I get from log cat is "Uncaught handler: thread main exiting due to uncaught exception"
Any suggestions? Thanks in advance
EDIT:
package com.whatever.main;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Next next = new Next();
TextView timesHit_txtview = (TextView) findViewById(R.id.textView2);
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timesHit_txtview.setText(5);
Button next_btn = (Button) findViewById(R.id.button1);
next_btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent nextscreen_intent = new Intent(view.getContext(), Next.class);
startActivityForResult(nextscreen_intent, 0);
}
});
}
}
You're trying to initialize a widget before the onCreate() call has been completed.
Initialize your TextView in the onCreate() method before you call setText on it, like so:
public class MainActivity extends Activity {
Next next;
TextView timesHit_txtview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
next = new Next(); // Initialize Next
timesHit_txtview = (TextView) findViewById(R.id.textView2); // Initialize Widget
timesHit_txtview.setText(5);
Button next_btn = (Button) findViewById(R.id.button1);
next_btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent nextscreen_intent = new Intent(view.getContext(), Next.class);
startActivityForResult(nextscreen_intent, 0);
}
});
}
In your current code, timesHit_txtview is null when you try to set a text for it, which makes you Activity crash.