This question already has answers here:
Calling activity class method from Service class
(7 answers)
Closed 5 years ago.
Here i am trying to call method of main activity class from Audio Service class.
but when i call the method like :-
new HomeActivity().previousChannel();
at that time activity class method get called but it also called oncreate() method automatically.
Please help me.
I will prefer you to use EventBus for communication between Classes,Fragments,Services whatever it may be.It is very simple, most reliable and efficient.
It can be achieved in just 3 Steps:
1.Define Events.
public static class MessageEvent { /* Additional fields if needed */ }
2.Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
3.Post Events.
EventBus.getDefault().post(new MessageEvent());
For more Details You can check here.
Hope it may help you.
you can use an interface with name MyCallBack that will be implemented by your activity with any method like do Something();
your activity will implement method of interface.
From your service class you need to call method of interface from variable of that interface type.
For that In your service class take a variable of type Interface like serviceCallBack and pass context of activity class in that variable.
from that variable you can call method of interface that will automatically take you to activity class and you can call your activity methods like update any UI component
Related
I have two activities Activity A and Activity B inside of the same application and they need to be able to call methods on each other. A needs to communicate to B at the start (possibly see "code" below).
B will call a lot of methods on A (this means that I cannot use the startActivityForResult method for communication because this would close B (Activity B is a Bluetooth Client and Server because it is a Peer to Peer app)). I do use startActivityForResult to start B for more of a kill signal than anything as the result.
Activity A uses a SupportMapFragment and Activity B cannot be a fragment because I want to be able to switch from B to A and then never use B again.
Originally, I started with one activity and tried switching between views using a ViewFlipper and just a call to setContentView(R.layout.my_layout_A) or setContentView(R.layout.my_layout_B). The fragment of course caused a lot of problems for both.
Using Fragments were confusing. The SupportMapFragment is the code for a Google Map which is a Fragment.
When I click a menu option inside of the MapsActivity (Activity A), I would like to be able to start myBluetoothActivity (Activity B) with a reference to the MapsActivity (Activity A) OR start myBluetoothActivity and then be able to set a reference to the caller inside of myBluetoothActivity (but this option would require having a reference to the BluetoothActivity inside of the MapsActivity or having some way to obtain the started activity from the intent).
//the following code is in Kotlin, but this can easily be converted over to java:
//option A: (pass it inside of the constructor)
var mbta:myBluetoothActivity = myBluetoothActivity(this)
//line for intent that I am unsure of
//intent so that I can start the activity with the pointer to the caller already passed into the new activity
startActivity(mbta)
//option B: (set this reference after obtaining a reference from intent):
var mintent:Intent = Intent(this.applicationContext, myBluetoothActivity::class.java)
startActivity(mintent)
//obtain the reference to the BluetoothActivity from the intent (NOT SURE HOW TO DO THIS???)
mbta.setCallerReference(this)
How can I accomplish this communication between the two activities via reference between the two activities? Should I use an interface for communication? If I should use it, (which I did try) how should I?
In other words, I am trying to access the caller activity (Activity A) from (Activity B) directly via a reference to Activity A inside of B OR trying to get the reference to B from the intent that started it inside of Activity A. I am trying to get a reference to that, so I can use it for communication/method calling/member variable and UI modification purposes.
NOTES: 1. The BluetoothActivity and the MapsActivity are NOT SERIALIZABLE. I tried serializing it and then adding it to the extras Bundle in the Intent and it just crashed saying that that was impossible to serialize due to BroadCastReciever. As this also deals with WIFI. Which I am highly considering separating out to be put with the BluetoothActivity in a future release.
I am also ASSUMING that Activity B will never just be started up by anything other than my MapsActivity class.
I am also new to Kotlin, but I know Java.
When I tried using an interface, I caused a StackOverflow error and I have no idea why.
I have read the documentation for Intents on the website.
I have done some research on here which gave me those ideas above. I am not sure how to implement them.
You are using the wrong approach. The solution requires a bit more work than you would think. The correct approach is to:
First, realize that these activities Activity A and Activity B (and any other activities) are activities that are specific to your application and you want to establish direct communication between them.
Second, realize that you are trying to get the current (or a previous) activity's context. The context will help serve the reference.
Third, you can create your own Activity and Application classes by extending the desired classes. The Application class is a low-level class used for the activities.
From here, you will be able to make use of the getApplicationContext() which will return your custom Application class.
Design: It is inside of your CustomApplication class that you must track the references to the activities that you want. From there all that you have to do is cast the getApplicationContext() to your CustomApplication class and then call your methods that access the Activity(ies). You must of course cast your Activities if you want to access certain instances of a specific activity that you created to its "type." For example:
MapsActivity mact = (MapsActivity)(((MyApplication)(this.getApplicationContext())).getCurrentActivity())
You must of course note that this activity must be already created (the onCreate method was already called) for this to return the current activity. The same of course goes for the other life-cycle methods for the activity as you will make a baseActivity which will deal with these as well as you will also have an Application life-cycle that will help deal with this too.
To answer the question: "How to get the current foreground activity context in android?" I turned to StackOverflow and found user: gezdy 's answer to be exactly what I needed at: How to get current foreground activity context in android?.
(BEGIN QUOTATION FROM: GEZDY)
You should manage activities references. Add the name of the
application in the manifest file :
<application
android:name=".MyApp"
....
</application>
Your application class :
public class MyApp extends Application {
public void onCreate() {
super.onCreate();
}
private Activity mCurrentActivity = null;
public Activity getCurrentActivity(){
return mCurrentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity){
this.mCurrentActivity = mCurrentActivity;
}
}
Create a new Activity :
public class MyBaseActivity extends Activity {
protected MyApp mMyApp;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMyApp = (MyApp)this.getApplicationContext();
}
protected void onResume() {
super.onResume();
mMyApp.setCurrentActivity(this);
}
protected void onPause() {
clearReferences();
super.onPause();
}
protected void onDestroy() {
clearReferences();
super.onDestroy();
}
private void clearReferences(){
Activity currActivity = mMyApp.getCurrentActivity();
if (this.equals(currActivity))
mMyApp.setCurrentActivity(null);
}
}
So, now instead of extending Activity class for your activities, just
extend MyBaseActivity. Now, you can get your current activity from
application or Activity context like that :
Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
(END OF QUOTATION FROM: GEZDY)
Note: All code is written in java for this answer.
I've been working on Xamarin for the past couple of years along with Android studio and I decided to create an application for a friend (full source code here https://github.com/nekrull/waiter don't be too harsh please :) )
The idea is that there is a base activity which exchanges fragments when a new screen should appear.
Fragments have everything that has to do with user interaction and the activity they are attached to handles the business logic.
To do this I have a base class CoreActivity/DataActivity which has some methods most Fragments use (like blocking the back button) and some helper methods (like calling a method on an attached fragment of a specific class) , a CoreInteraction that responds to this activity and
CoreFragment/AttachedFragment which is used as the base of all view fragments
so for example the view fragment would look like this:
public class GroupsFragment extends AttachedFragment<GroupsFragment.GroupsInteraction> {
//this is what we expect to be able to call in the parent
public interface GroupsInteraction extends CoreInteraction {
Group get_shown_group();
void new_group();
void select_parent();
}
}
which is basically a fragment that expects its attached activity to be able to respond to the interaction methods.
the activity fragment would look like this:
public class MainActivity extends DataActivity<MainData> implements
GroupsFragment.GroupsInteraction, (other interactions here) {
}
The problem is that since the application I'm working on has only one Activity with many small screens, the code inside the base activity will get big, that does not cause a problem with the application or compiling or anything else. But it makes it really hard to find what I'm looking for easily.
What I used to do in Xamarin is something like this:
public partial class MainActivity : DataActivity<MainData> {
}
for the initialization activity and then each interaction would get its own file like this:
public partial class MainActivity : GroupsInteraction {
}
It had the same effect (since the class is compiled as a single class) but the code would be tidy and easy to read.
Obviously there are no partial classes in Java, but is there a way to delegate the implementation of an interface to another class?
Something along the lines of saying "when you're invoking a method from interface a, invoke it from that class" without actually writing stuff like :
public Group get_shown_group() {
return new GroupHandler(this).get_shown_group();
}
public void new_group() {
new GroupHandler(this).new_group();
}
public void select_parent() {
new GroupHandler(this).select_parent();
}
Thanks in advance for any help you can provide
Something along the lines of saying "when you're invoking a method from interface a, invoke it from that class"
Taking you literally what you describe is plain delegation, a class does not implement some or any functionality itself, instead it wraps a class implementing the desired functionality, calling the methods of said wrapped class. You could even switch implementation at runtime, just changing the wrapped class as you go (assuming the classes share a common interface, of course). Of course that does not "spare" you from writing the delegations yourself.
class Wrapper implements GroupsInteraction {
private final GroupInteraction gi;
public Wrapper(GroupsInteraction gi) {
this.gi = gi;
}
Group get_shown_group() {
return this.gi.get_shown_group();
}
// ... other interface impls
}
Additionally, you should keep the GroupHandler as a member instead of creating a new Object each time, so
public Group get_shown_group() {
return new GroupHandler(this).get_shown_group();
}
becomes
public Group get_shown_group() {
return this.groupHandler.get_shown_group();
}
You can try Delegation Pattern
BaseActivity {
MyDelegateClass delegate;
void example() {
delegate.example();
}
}
P.S. both activity and delegate implements same interface
Details here
I am having this issue where I have nested fragments. I need one to be able to send information to the other.
For example, if I press a button in the inner fragment I want the outer fragment to perform an action.
Any help would be great!
Edit: I forgot to mention that both of these are live fragments. As far as I know using bundles only allows me to set arguments when creating a fragment but not after it has been created.
Well there are plenty of ways to manage this. It really depends on the architecture you want to go with.
You could go lazy and use a Bus library that uses sub/pub modeling and reflection for notifying generic objects that registered and have matching signature methods of changes, However, this is frowned upon to use reflection for regular coding practices that could be implemented without it.
I would say you can either create an interface that represents the calls that would go back and forth like IMainActivityCallbacks with methods like dataChange(myObject obj)
.
Then in your onAttach of fragment you cast the context as IMainActivityCallbacks. Make sure the MainActivity implements the interface.
Then simply call the mIMainActivityCallbacks.dataChange(someObject);
This will call the method in the parent activity and allow him to pass it to the child fragment that needs it with mMyOtherFragment.publicMethod(newDataJustReceived).
You could also get crazier if you want and pass an interface into the child fragment that references the outer fragment so when MainActivity news up the children fragment, the outer one could implement an interface of doStuff and then be passed as an interface to the inner child fragment. So the child fragment can easily say if "mParentInterface" is not null then mParentInterface.doStuff.
There are millions of ways to skin a cat, but prefer to use interfaces rather then Reflection based libraries typically. Hope that helps.
Use interface in this case. 1) Define interface in you first fragment(in which you click something and waiting something to happen in a second fragment) and use callback method you define in your interface. For example:
OnButtonClickListener mCallback;
......your code
public interface OnButtonClickListener {
void onButtonSelected(int position);
}
......your code
then you call your callback method
.....
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
mCallback.onButtonSelected(position);
}
});
2) Then implement this interface in host activity you have for nested fragments.
For example:
public class MainActivity extends AppCompatActivity implements YourFragment.OnButtonClickListener{....
3) Define callback method of your interface in this activity. For example:
public void onButtonSelected(int position) {
...Here just change something in your second fragment.....
Hope this will be helpful.
I use greenrobot EventBus in that cases.
You need to add this library to your build gradle:
compile 'org.greenrobot:eventbus:3.0.0'
That you can send message like this:
EventBus.getDefault().post(new ActionEvent("test action"));
And another fragment can catch it this way:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onActionEvent(ActionEvent event) {
//do something
}
You can sending different actions, if you want, same way.
Don`t forget to according to fragment lifecycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
I create a Interface to pass gcm id from GCMBaseIntentService class to my Application MainActivity.
My Interface is ::
public interface GcmId {
public void sendGcm(String id);
}
How can call this interface in GCMBaseIntentService class and pass it in MainActivity Interface implemention.
Thanks
Instead of creating complicated ways to pass the registration ID from your intent service to your activity, you can store it in SharedPreferences, and access it where ever it is needed.
Even better, you don't have to use GCMBaseIntentService, which is a deprecated class. You can use the new synchronized registration method GoogleCloudMessaging.register(), which you can call in your main activity (though you should run it in the background), and get the result without involving any broadcast receiver or intent service.
In the application i'm making I want to start an intent in one activity
Intent toonService = new Intent(Login.this, ToonService.class);
toonService.putExtra("toonName", result.getName());
Login.this.startService(toonService);
Will the following code close the intent i just opened? If not how can i get it to?
Intent toonService = new Intent(MainActivity.this,ToonService.class);
MainActivity.this.stopService(toonService);
the second piece of code would be called at a time completly unrelated to the first piece of code.
Well, assuming you only want one instance of this service running at once you could hold a static variable in the service class and access it from anywhere. Example;
public class ToonService extends Service{
public static ToonService toonService;
public ToonService(){
toonService = this;
}
...
}
The constructor for ToonService now stores the created instance in the static variable toonService. Now you can access that service from anywhere from the class. Example below;
ToonService.toonService.stopSelf();
You could also handle multiple instances by having the class store a static List of running instances, rather than just the single instance. It is worth noting, that when you tell a service to stop, you are only requesting that it is stopped. Ultimately the Android OS will determine when it is closed.
Definitely you can close the service from another activity.
Method-1: Do the following steps
1. Write a method in Activity 1 that returns that activity reference.
2. Write a method in Activity 1 that closes the service.
3. In Activity2 call the first method and get the reference. Using that reference call the second method
1. private static Context context=this;
public static Context getContext(){
return context;
}
2. public void stop(){
//stop the service here
}
3. In activity 2
Activity context=Activity1.getContext();
context.stop();
Method 2: follow the following steps.
Write a BroadcastReceiver as an inner class in Activity1 . In onReceive() stop the service.
Broadcast the intent from the second Activity.