How to call a method in an Activity from another class - java

I am working on an SMS application and I have a method in my MainActivity to perform a button click:
public void updateMessage() {
ViewMessages.performClick();
}
This method works fine and performs the button click when I call this method from inside the MainActivity class.
But, when I call this method from any other class as shown below, where I call the Main Activity's updateMessage method from the IntentServiceHandler class, I am getting a NullPointerException:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.widget.Button.performClick()' on a null object reference
public class IntentServiceHandler extends IntentService {
public IntentServiceHandler() {
super("IntentServiceHandler");
}
#Override
protected void onHandleIntent(Intent intent) {
String message = intent.getStringExtra("message");
TransactionDataBase transactionDB = new TransactionDataBase(this, 1);
transactionDB.addMessage(message);
MainActivity mainActivity = new MainActivity();
mainActivity.updateMessage();
}
}
How can I handle this?
Edit: I even tried to make the updateMessage method static, and now i get the following exception
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Don't call the method of Activity in an IntentService, try to use Intent to communicate between Activity and IntentService.
Replace the last two statements onHandleIntent() with
Intent intent = new Intent();
broadcastIntent.setAction(MainActivity.UPDATE_MESSAGE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(intent);
And you should register a BroadcastReceiver in onCreate() of MainAcitivty like
private BroadcastReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState){
// ....
IntentFilter filter = new IntentFilter();
filter.addAction(UPDATE_MESSAGE);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do something based on the intent's action
// for example, call updateMessage()
}
};
registerReceiver(receiver, filter);
}
onHandleIntent of IntentService run in another thread (instead of main thread / ui thread), so Updating UI components in onHandleIntent isn't permitted.

Related

LocalBroadcastManager not receiving messages correctly

I have a, what I thought was a, simple task. I have a list of achievements in a recyclerView in my MainActivity. Clicking on one of the achievements launches the AchievementDetailActivity. You do an action in the AchievementDetailActivity and it completes the achievement. When that happens, I need the thumbnail on the MainActivity to be the achievement icon and not the locked icon. What I thought was I could just use the LocalBroadcastManager to send and receive messages from one activity to another, but that isn't working. From everything I have read you are supposed to unregister the listener in your activity onPause and onStop lifecycle methods, however, if you unregister the listener in the onPause of MainActivity, it gets unregistered when the AchievementDetailActivity starts and nothing gets delivered to the MainActivity. I don't understand how you can use LocalBroadCastManager with receivers to send information between activities when they get unregistered as soon as you start a new activity. The following example shows it unregisters as soon as the second activity is started, so the first activity will never get the broadcast...
public class MainActivity extends AppCompatActivity {
public static final String ACTION = "update";
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MAIN ACTIVITY", "RECEIVED EVENT");
}
}
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver), new IntentFilter(ACTION));
}
public void onPause() {
Log.d("MAIN ACTIVITY", "REMOVING LISTENER");
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
//.. The rest of MainActivity
}
public class SecondActivity extends AppCompatActivity {
#Override
public void onStart() {
super.onStart();
//initialize view and such
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
Intent intent = new Intent(MainActivity.ACTION);
intent.putExtra("Something", "somewhere");
manager.sendBroadcast(intent);
}
)};
}
If you run the above, obviously with the buttons and such, you will get a message that shows it unregisters the listener as soon as SecondActivity starts and the MainActivity will never get the message it is supposed to get when you click a button on the second activity.
Is there a way to send information from activity to activity, or because of the lifecycle events is that not possible? Everything I read said LocalBroadcastManager was the right way to do it, but it gets unregistered so, how can it? Please help, this is driving me nuts. Thank you.
If you want to use your LocalBroadcastManager to fetch results, do not unregister in onPause, in which case must to unregister in onDestroy().
If you startAvtivity only to fetch some results, it is a good way to startActivityForResult.
Its not a great idea to use LocalBroadcastReceiver for this purpose. Use startActivityForResult instead. Follow this Official doc for implementation details.
The reason its not wokring is:
You are registering the receiver in onStart and unregistering it in onPause(). When your second activity is shown, onPause () will be called as a result the BroadcastReceiver is unregistered.
Its not a great idea to keep it registered since it would lead to memory leaks.

How to start a new activity and start a method in that activity

So I'm working with Java in android studio and I want to start a new class from a different class (I'm in ListenerServiceFromWear and want to start MainActivity) and once Mainactivity is started I want to start a method (startEmergencyMode();) in Mainactivity.
How do I do this from ListenerServiceFromWear?
Start MainActivity with an intent and in the extra of the intent put some flag that will tell MainActivity to call startMergencyMode()
Intent intent = new Intent(this, Mainactivity.class);
intent.putExtra("isEmergency", true);
startActivity(intent);
And then in Mainactivity actually call startEmergencyMode()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
Intent intent = getIntent();
boolean isEmergency = intent.getBooleanExtra("isEmergency", false);
if(isEmergency){
startEmergencyMode();
}
}
I don't quite understand what you mean by "start"
In java, you either:
Declare a static field or method
Create an instance of an object and use its public fields and methods.
If you wish to just have one 'instance' of MainActivity, use a static method:
public static void startEmergencyMode() {
// Code here
}
Which you can call anywhere using MainActivity.startEmergencyMode().
Keep in mind that this static method can only access static fields and other static methods.
If you wish to create an instance of MainActivity, simply create one and call the method:
public void startEmergencyMode() {
// Code here
}
// Somewhere else
MainActivity activity = new MainActivity();
activity.startEmergencyMode();
If you don't understand the difference between a static and non static method or field, refer the answer on this thread: What does 'public static void' mean in Java?

Returning string from Android Activity started with `startActivityForResult` inside `onClickListener` returns null

I use an Intent in MainActivity to start another Activity called MatchesActivity using startActivityForResult. I put breakpoints at finish() inside the started activity (MatchesActivity) and on the Log statement inside onActivityResult because I got NPE inside onActivityResult.
intent.getStringExtra("TXAMATCHES") contains what it should.
But Intent data comes back null.
Is this likely/possibly because I start the Intent inside an onClick listener?
Or because MatchesActivity calls a method in another class that extends AsyncTask and the data is what that task produces? (But the correct data is found in txaMatches just before it is returned to MainActivity...)
public class MainActivity extends Activity
{
...
btnSearch.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v)
{
...
Intent matchesIntent;
matchesIntent = new Intent(MainActivity.this, MatchesActivity.class);
startActivityForResult(matchesIntent, 0);
...
}
...
#Override protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.w("MainActivity","" + onActivityResult " + data.getStringExtra("TXAMATCHES"));
}
}
...
public class MatchesActivity extends Activity implements DatabaseConnector.DatabaseProcessListener
{
...
#Override protected void onDestroy()
{
super.onDestroy();
finishThisAndReturnString();
}
public void finishThisAndReturnString()
{
Intent intent = new Intent();
intent.putExtra("TXAMATCHES",txaMatches.getText().toString());
setResult(RESULT_OK, intent);
finish();
}
(The started Activity is terminated by user pressing back icon.)
You can't finish a activity in the onDestroy method. In this lifecycle phase the activity is already dying.
The call of the finish() method will call the onDestroy, not the other.
Call the finish method when you want to to finish the MatchesActivity.
What you're trying to do is not correct. You're trying to call finish() on the onDestroy() method. onDestroy() gets called when the Activity is about to be killed. So basically calling finish() at that point is wrong.
I assume that you are trying to do some processing in the AsyncTask. I suggest that you call the finish() method on the onPostExecute() method of the AsyncTask.
You are setting the data in the Intent object in onDestroy() method . So in this case, whenever you call setResult() in onDestroy() method, you will always get resultCode in onActivityResult() as '0' which is the value for RESULT_CANCELED and whenever you get RESULT_CANCELED in onActivityResult() you get data object null. That's why you don't get the values you set in Intent .
First try to get the value of
txaMatches.getText().toString()
Check this value in the MatchesActivity Class.
It is possible that it is returning null value due to which u are getting the problem.
The problem is fixed by removing finishThisAndReturnString() from onDestroy, as stated in the first two Answers.

Android: how do I tell my activity to start new activity from my service?

I have a service that is, among other things, downloading images from internet. When this is done I want to show this image in a custom Activity that has a dialog theme. But I only want to use this pop up if the app is running, otherwise I just want to create a notification.
But I get an exception when I try to start an activity from my service and i feel that maybe this isn't the right way to do it?
It says:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So my question is if this is the right way to do this by setting that flag or how should I get my downloaded image from my service to an activity. Can I in some way tell an activity to start a new activity from my service class?
I think using Broadcast Receiver is better option for you.
Add Below Method in Service and call this method when image Download Complete.
private void updateMyActivity(Context context) {
if(MainActivity.activityStatusFlag){
//update the activity if activityStatusFlag=true;
Intent intent = new Intent("mUpdateActivity");
context.sendBroadcast(intent);
}else{
//display notification if activityStatusFlag=false;
}
}
In Activity Add Following Code.
public class MainActivity extends Activity{
public static boolean activityStatusFlag= false;
//define this variable to check if activity is running or not.
#Override
protected void onResume() {
super.onResume();
activityStatusFlag = true;
this.getApplicationContext().
registerReceiver(mMessageReceiver,new IntentFilter("mUpdateActivity"));
}
#Override
protected void onPause() {
super.onPause();
activityStatusFlag = false;
this.getApplicationContext().unregisterReceiver(mMessageReceiver);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Display Popup or update Activity
}
};
}

Get context of current running activity

I wonder if there is a way to get the context of current running activity on android. For example, I have an Activity Class and it is running. What I want is to call another Simple Class to run some functions which called from Activity Class. By doing this, I need to set up a context of Activity Class on Simple Class; On the other way, I need to have the context of Current Running Activity, so that my Simple Class can actually run the functions called from Current Running Activity.
Below is the soft code from my project.
public class Main1 extends Activity {
private static GetAPNsInfo getAPNsInfo = new GetAPNsInfo();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getAPNsInfo.doSomething();
}
}
public class GetAPNsInfo {
public void doSomething() {
Button button = currentRunningActivityContext.findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
});
}
}
Finally, my purpose of this thread is that I need a good way to get the current running activity info.
This is a solution that I found my self. But it doesn't totally solve this case. We can add a receiver in Manifest.xml. This will run a background application.
<receiver android:name=".RunningActivityCapture">
<intent-filter android:priority="-1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
</intent-filter>
</receiver>
The background application interface look like this:
public class RunningActivityCapture extends BroadcastReceiver {
#Override
public void onReceive(Context aContext, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_ALL_APPS)) {
Activity activty = intent.getCurrentActivity();
Session session = new Session();
session.setRunningActivity(activty);
}
return;
}
}
I only get the activity from session class which setting from my background application. This is my first idea to solve this problem. But the code is not correct. So I need your help.
If you are asking how to use this MainActivity in your helper class, you can pass the Activity itself into your class, as an activity is a Context. So your constructor will be:
public GetAPNsInfo(Context context) {
...
}
where you store the context in a field and use it later. You will initialize with
private static GetAPNsInfo getAPNsInfo = new GetAPNsInfo(this);
if you are asking how to get the context for ANY activity in your application, I don't think that is recommended.

Categories