Android - Stop a Service from a different class - java

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.

Related

Clear Difference Between 'application' and 'activity' [duplicate]

An extended Application class can declare global variables. Are there other reasons?
Introduction:
If we consider an apk file in our mobile, it is comprised of
multiple useful blocks such as, Activitys, Services and
others.
These components do not communicate with each other regularly and
not forget they have their own life cycle. which indicate that
they may be active at one time and inactive the other moment.
Requirements:
Sometimes we may require a scenario where we need to access a
variable and its states across the entire Application regardless of
the Activity the user is using,
An example is that a user might need to access a variable that holds his
personnel information (e.g. name) that has to be accessed across the
Application,
We can use SQLite but creating a Cursor and closing it again and
again is not good on performance,
We could use Intents to pass the data but it's clumsy and activity
itself may not exist at a certain scenario depending on the memory-availability.
Uses of Application Class:
Access to variables across the Application,
You can use the Application to start certain things like analytics
etc. since the application class is started before Activitys or
Servicess are being run,
There is an overridden method called onConfigurationChanged() that is
triggered when the application configuration is changed (horizontal
to vertical & vice-versa),
There is also an event called onLowMemory() that is triggered when
the Android device is low on memory.
Application class is the object that has the full lifecycle of your application. It is your highest layer as an application. example possible usages:
You can add what you need when the application is started by overriding onCreate in the Application class.
store global variables that jump from Activity to Activity. Like Asynctask.
etc
Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
For example, if you want to get the basic authentication data for each http request, you can implement the methods for authentication data in the application object.
After this,you can get the username and password in any of the activities like this:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
And finally, do remember to use the Application object as a singleton object:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
For more information, please Click Application Class
Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.
I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.
The Application class is a singleton that you can access from any activity or anywhere else you have a Context object.
You also get a little bit of lifecycle.
You could use the Application's onCreate method to instantiate expensive, but frequently used objects like an analytics helper. Then you can access and use those objects everywhere.
Best use of application class.
Example: Suppose you need to restart your alarm manager on boot completed.
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
Not an answer but an observation: keep in mind that the data in the extended application object should not be tied to an instance of an activity, as it is possible that you have two instances of the same activity running at the same time (one in the foreground and one not being visible).
For example, you start your activity normally through the launcher, then "minimize" it. You then start another app (ie Tasker) which starts another instance of your activitiy, for example in order to create a shortcut, because your app supports android.intent.action.CREATE_SHORTCUT. If the shortcut is then created and this shortcut-creating invocation of the activity modified the data the application object, then the activity running in the background will start to use this modified application object once it is brought back to the foreground.
I see that this question is missing an answer. I extend Application because I use Bill Pugh Singleton implementation (see reference) and some of my singletons need context. The Application class looks like this:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
#Contract(pure = true)
#Nullable
public static Context getAppContext() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
And the singletons look like this:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
#Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
#SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
This way I don't need to have a context every time I'm using a singleton and get lazy synchronized initialization with minimal amount of code.
Tip: updating Android Studio singleton template saves a lot of time.
I think you can use the Application class for many things, but they are all tied to your need to do some stuff BEFORE any of your Activities or Services are started.
For instance, in my application I use custom fonts. Instead of calling
Typeface.createFromAsset()
from every Activity to get references for my fonts from the Assets folder (this is bad because it will result in memory leak as you are keeping a reference to assets every time you call that method), I do this from the onCreate() method in my Application class:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
Now, I also have a method defined like this:
public static App getAppInstance() {
return appInstance;
}
and this:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
So, from anywhere in my application, all I have to do is:
App.getAppInstance().getQuickSandRegular()
Another use for the Application class for me is to check if the device is connected to the Internet BEFORE activities and services that require a connection actually start and take necessary action.
Source: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
In many apps, there's no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
Specialized tasks that need to run before the creation of your first activity
Global initialization that needs to be shared across all components (crash reporting, persistence)
Static methods for easy access to static immutable data such as a shared network client object
You should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
To add onto the other answers that state that you might wish store variables in the application scope, for any long-running threads or other objects that need binding to your application where you are NOT using an activity (application is not an activity).. such as not being able to request a binded service.. then binding to the application instance is preferred. The only obvious warning with this approach is that the objects live for as long as the application is alive, so more implicit control over memory is required else you'll encounter memory-related problems like leaks.
Something else you may find useful is that in the order of operations, the application starts first before any activities. In this timeframe, you can prepare any necessary housekeeping that would occur before your first activity if you so desired.
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
You can access variables to any class without creating objects, if its extended by Application. They can be called globally and their state is maintained till application is not killed.
The use of extending application just make your application sure for any kind of operation that you want throughout your application running period. Now it may be any kind of variables and suppose if you want to fetch some data from server then you can put your asynctask in application so it will fetch each time and continuously, so that you will get a updated data automatically.. Use this link for more knowledge....
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android

Communication Between Two Android Activities via Reference to Caller or Callee

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.

How to wait for the service to load before starting the activity

The Service class will load a library and it takes about 4-5 seconds for the library to become ready. What is the best way to make MainActivity to keep checking on the status of a static boolean in Service class and do something when it's ready? I looked around and knew that using busy wait loop is bad.
The outline of my planned MainActivity is
onCreate - start the service
onResume - show the splash screen until a specific boolean in Service become true then switch to another fragment
You could use a broadcast receiver from the Service to your MainActivity which triggers a method inside the MainActivity... instead of constantly checking a static bool in the service.
But you want to be very sure to handle cases where it never loads for whatever reason, otherwise users will be staring at a splash screen forever.
Simple solution is Broadcast Reciever Try this
BroadcastReceiver broadCastNewMessage = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do your stuff here
}
};
Now in onCreate() register this
registerReceiver(this.broadCastNewMessage, new IntentFilter("bcNewMessage"));
And in onDestroy()
unregisterReceiver(broadCastNewMessage);
Now Call this method from the service class where u want to update the activity
sendBroadcast(new Intent().setAction("bcNewMessage"));

nullPointerException Crash On Call after App Minimized Long Time

there is Class Named "Configs.java" contains :
public Contect context;
public Activity currentActivity;
On Global Class Named "App.java" :
public static Configs configs = new Configs();
On Main Activity Java Class Oncreate :
App.configs.context = getApplicationContext();
App.configs.currentActivity = this;
On Products Activity Java Class Oncreate (Main Activity Not Finished And Must Work In Background):
App.configs.currentActivity = this;
After Long Time Minimized , it shows An Error On Bellow Line From Products Activity Java Class :
App.configs.currentActivity = this;
NullPointerException
Unable To Use "Bundle savedInstanceState" Because It's Activity Valiable
Try moving this code to onResume() instead of onCreate() and see if the error still exists.
Using static variables on Android is no good. This post explains that Android is very likely to kill your app (kills your Application instance, hence the static variable becomes null when your app is recreated and the class loader reinstantiates your vars) to save memory. The post also refers to Saving Activity state in Android which offers an alternative to save stuff with Bundles.
Anyway, if you need a quick solution, make your Configs class a singleton, and use getters and setters instead of making it public. Make the getter check if your singleton is null, and in this case, instantiate a new and return it. You won't get NPEs but it is very risky since it won't restore the previous state.

Pass gcm Registration Id from GCMBaseIntentService class to MainActivity via Interface in android

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.

Categories