Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have made an App in android in which i have a TCP Client but now i want to send a message to the server only when the app is going to be closed, i've trying to add the openConnection (opening connection with TCP Client) and sendMessage (Sending message to the TCP server) action in onDestroy method but that didn't worked.
The TCP Client i've used is in this guide, actually i need to send this message for communicate the server that the communication with the device is closed and send message "Device is Offline" and just then close the app.
Method 1: You can use ActivityLifecycleCallbacks to achieve this. There's an example with some logs below.
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private int mVisibleCount;
private boolean mInBackground;
#Override public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override public void onActivityStarted(Activity activity) {
mVisibleCount++;
if (mInBackground && mVisibleCount > 0) {
mInBackground = false;
Log.i(TAG, "App in foreground");
}
}
#Override public void onActivityResumed(Activity activity) {
}
#Override public void onActivityPaused(Activity activity) {
}
#Override public void onActivityStopped(Activity activity) {
mVisibleCount--;
if (mVisibleCount == 0) {
if (activity.isFinishing()) {
Log.i(TAG, "App is finishing");
} else {
mInBackground = true;
Log.i(TAG, "App in background");
}
}
}
#Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override public void onActivityDestroyed(Activity activity) {
}
});
}
public boolean isAppInBackground() {
return mInBackground;
}
public boolean isAppVisible() {
return mVisibleCount > 0;
}
public int getVisibleCount() {
return mVisibleCount;
}
}
Method 2: There's another method using Service to detect if application is terminated. See link
Following method call on diff action
Minimize the Application using home button --> this calls
onPause()
onStop()
Remove the app from Task Manager ->
then onDestroy() is called for that MainActivity (launcher).
So Make an parent Activity suppose named BaseActivity and override its
onPause(), onDestroy() and onStop() method and call your
implementation from here and then extend this Activity from your
another Activities
You should not rely on the onDestroy method. As per the official android documentation it is not called always.
Try to put the same code in the onStop() method of your activity.
Additionally you can have a parent activity which is extended by all other activities.
You can then override the onPause() and onStop() method in your particular child activities and handle the specific scenarios.
Related
I am only starting with Java/Android and trying to implement custom SDK.
I am making Capacitor plugin for android, but for now trying to do Android side logic.
I have method that I want to be able to execute on demand AndroidConfigManager.stopDetection(getActivity()); which enables/disables NFC read.
so If I execute AndroidConfigManager.stopDetection(getActivity()); I get NFC Detection Enabled in log and all is good.
However that executes every time app goes to background and resumes after. I've tried to override onPause and onResume but the way I have it doesn't seem to be doing anything.
I can't figure out how to suppress it
public class ExamplePlugin extends Plugin implements IDetectCardCallback, IITSOFrameworkCallback, ITransactionControllerCallback {
private Application app;
private Context context;
public void echo(PluginCall call) {
String value = call.getString("value");
app = getActivity().getApplication();
context = getContext();
AndroidConfigManager.initialise(app);
AndroidConfigManager.stopDetection(getActivity());
}
#Override
public void onResume(){
super.onResume();
AndroidConfigManager.stopDetection(getActivity());
// ITSOFramework.getInstance().detectCard(this, false);
}
#Override
public void onPause(){
super.onPause();
// ITSOFramework.getInstance().detectCard(null, false);
}
}
I'm using greenrobot EventBus and have some misunderstandings how to use it.
In my app, I have 4 activities: MainActivity and 3 other. Each Activity have it's own role in app, and MainActivity holds connection via COM port and sends/receives messages. So, when message is received, it sends via EventBus to current working activity. And when other Activity needs to sent message to COM port, it sending message to MainActivity via EventBus too. Problem is that when I'm working in one activity - all works fine, but when I try to do something in other activities - messages from EventBus are duplicaed. There is more - when I try to work in third activity - message is multiplies by 3 and so on.
Here some code:
public class ManualControl extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//my other code here
}
#Override
protected void onPause()
{
super.onPause();
EventBus.getDefault().unregister(this);
}
#Override
public void onResume()
{
super.onResume();
EventBus.getDefault().register(this);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEventFromMain event)
{
//code to do when get message from MainActivity
};
private void sendMessage(String messageID, String messageName)
{
EventBus.getDefault().post(new MessageEventFromIntent(messageID, messageName));
}
}
This method I use to send message to another Activity from MainActivity
EventBus.getDefault().post(new MessageEventFromMain(messageFromSerial));
And catch event from other Activities in MainActivity
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventFromIntent(MessageEventFromIntent event)
{
//code to do when get message from intent
}
As you can see, I'm unregistering onPause() and registering onResume(), but when I'm closing this activity and starting it again messages are duplicating.
Example:
1st use:
55017031011_TURN_STRAIGHT27
2nd use:
55017031011_TURN_STRAIGHT2755017031011_TURN_STRAIGHT27
I have readed gitHub issues, but not found any answer.
And sorry for mistakes.
Unregister MainActivity from MessageEventFromIntent event after the activity is closed.
I'm trying to add a custom quick settings tile for my application. I've followed the sample code/documentation from Google but I'm running into some issues. After searching for some time I couldn't find any solutions.
When I run my app, the tile is visible in the quick settings tray, but it remains in an unavailable state.
I need a two-way flow of communication with the tile, i.e., when the user selects the tile, the app responds and when the user does a certain action within the app, the tile UI is toggled.
The problem seems to come from attempting to bind my custom TileService class to my MainActivity -- whenever I bind it is when the tile goes into a consistently unavailable state. I can't seem to figure out why though because it's being bound successfully. If I don't bind it (i.e. just have the one way communication of the tile commanding the app), the tile is active and the app responds to selecting it.
Ultimately I do the binding to attain a reference to my custom TileService class to be able to call it's method toggleTileUI(). I'm not looking to use a singleton or static member variable as a solution to getting a reference to my service.
Here's what I have in my AndroidManifest.xml:
<service
android:name=".ConnectionQuickSettingsService"
android:label="#string/quick_setting_tile_connect"
android:icon="#drawable/tile_icon"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
Here's my ConnectionQuickSettingsService.java:
#TargetApi(24)
public class ConnectionQuickSettingsService extends TileService {
private static final String TAG = "ConnectionQuickSettingsService";
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
ConnectionQuickSettingsService getService() {
return ConnectionQuickSettingsService.this;
}
}
#Override
public IBinder onBind(Intent i) {
return mBinder;
}
#Override
public void onTileAdded() {
L.d(TAG, "onTileAdded()");
}
#Override
public void onStartListening() {
L.d(TAG, "onStartListening()");
}
#Override
public void onClick() {
L.d(TAG, "Quick Settings tile selected");
toggleInAppSwitch();
toggleTileUI();
}
private void toggleInAppSwitch() {
doStuff();
}
public void toggleTileUI() {
Tile tile = this.getQsTile();
doStuffWithTile();
}
}
and lastly (the relevant parts of) my MainActivity.java:
#Override
protected void onStart() {
super.onStart();
Intent i = new Intent(this, ConnectionQuickSettingsService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
ConnectionQuickSettingsService.LocalBinder binder = (ConnectionQuickSettingsService.LocalBinder) service;
mQSService = binder.getService();
mBound = true;
L.d(TAG, "Bound to QS service successfully");
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
L.d(TAG, "Disconnected from QS service");
}
};
public void onOnOff(){
L.d(TAG, "On/Off switch toggled");
if (mBound) {
mQSService.toggleTileUI();
}
}
Any input would be greatly appreciated, thanks!
Part of your problem is that you are overriding onBind(), which clobbers the TileService implementation of onBind(), preventing Android from working with your ConnectionQuickSettingsService. I would expect that there would be error messages in LogCat from a system process complaining about this.
The other part of your problem is that you assume that getQsTile() works at arbitrary points in time. It doesn't.
I recommend finding some other interaction pattern with your tile, such as using META_DATA_ACTIVE_TILE and requestListeningState(), and getting rid of your Binder and onBind() method.
I don't think you need all the service connection. I would add the meta data META_DATA_ACTIVE_TILE to the tile service manifest declaration, and then you can call TileService.requestListeningState(context, new ComponentName(context, TileService.class)); which will trigger onStartListening().
After that onStartListening() could call a method to update the Tile state/label/icon.
Also in your Tile service method to update the tile
I would add a check if (getQsTile !=null)
I have a BaseActivity that gets extended by every other activity. The thing is, I have the music muted whenever the user leaves (onPause) the activity. I also stop listening for telephone calls. The problem is, onPause is getting called whenever the user switches between activities, meaning the app is unnecessarily muting and stopping telephonymanager, even though it should only be muting and stopping telephonymanager if the user were to leave the app.:
#Override
protected void onPause() {
Log.v(TAG, "IN onPause!");
// unregister phone listener to telephony manager
tManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
mute();
super.onPause();
}
Now say I switch between public class myClass extends BaseActivity and switch to public class myOtherClass extends BaseActivity. This switch is unnecessarily executing onPause, even though I only want onPause to be called when the user leaves the app. What should I do?
Thanks for the expert advice,
Rich
From my understanding you are muting your music playing in onPause of BaseActivity, instead of that write it inside your Music play activity
Ex :
public class BaseActivity extends AppCompatActivity{
#Override
public void onPause(){
//do things that common for all activities
}
}
public void MusicPlayActivity extends AppCompatActivity{
#Override
public void onPause(){
music.mute()
}
}
This will work
UPDATE
There are few ways to detect whether your application is running in the background, but only one of them is completely reliable:
Track visibility of your application by yourself using Activity.onPause, Activity.onResume methods. Store "visibility" status in some other class.
Example
: Implement custom Application class (note the isActivityVisible() static method):
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
Register your application class in AndroidManifest.xml:
<application
android:name="your.app.package.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
Add onPause and onResume to every Activity in the project (you may create a common ancestor for your Activities if you'd like to, but if your activity is already extended from MapActivity/ListActivity etc. you still need to write the following by hand):
#Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
#Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
ActivityLifecycleCallbacks were added in API level 14 (Android 4.0). You can use them to track whether an activity of your application is currently visible to the user. Check Cornstalks' answer below for the details.
From your comments you only want to stop the music when the last Activity of your application is exiting. Overriding the finish() method of your BaseActivity like this should accomplish what you want:
#Override
public void finish() {
super.finish();
if (isTaskRoot()) {
// This is the last Activity in the stack so mute your music here...
}
}
Actually you probably want onDestroy() or onStop() as I'm not sure finish() executes unless you call it but the idea is the same:
#Override
protected void onDestroy() {
super.onDestroy();
if (isTaskRoot()) {
// This is the last Activity in the stack so mute your music here...
}
}
Here's info on isTaskRoot():
Return whether this activity is the root of a task. The root is the first activity in a task.
Returns
True if this is the root activity, else false.
I'm relatively new to Android,
I have read related articles on detecting network connectivity changes and have implemented this BroadcastReceiver subclass, made the necessary additions to AndroidManifest.xml and I receive the requisite state change broadcasts as expected:
public class NetworkStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
Question is: how can I receive or forward these notifications in/to my Activity subclasses? Apparently creating an instance of NetworkStateReceiver in my Activity subclass and overriding onReceive there doesn't do the trick.
Thanks in advance for any pointers...
Edit:
I ended up broadcasting an Intent from onReceive above like so:
Intent target = new Intent(CONNECTIVITY_EVENT);
target.putExtra(CONNECTIVITY_STATE, networkInfo.isConnected());
context.sendBroadcast(target);
And receiving that in my Activity like so:
#Override
protected String[] notifyStrings() {
return ArrayUtils.addAll(super.notifyStrings(), new String[] {NetworkStateReceiver.CONNECTIVITY_EVENT});
}
#Override
protected void notifyEvent(Intent intent, String action) {
super.notifyEvent(intent, action);
if (action != null) {
if (action.equalsIgnoreCase(NetworkStateReceiver.CONNECTIVITY_EVENT)) {
boolean isConnected = intent.getBooleanExtra(NetworkStateReceiver.CONNECTIVITY_STATE, true);
// Do something...
}
}
}
I would recommend using either
1) An interface approach. So declare an interface that has a networkChanged() method, and have the class which owns this BroadcastReceiver keep a list of classes who want to be notified of network changes with a local List<InterfaceName>
2) Skip the interface creating and use a subscription utility. My two favorites are
https://github.com/greenrobot/EventBus
and
https://gist.github.com/bclymer/6708819 (smaller, less used, also disclaimer: I wrote this)
With these you would create event classes with properties, and then subscribe and post instances of those classes.
In your activity
#Override
public void onCreate() {
...
EventBus.getInstance().subscribe(this, MyType.class);
}
#Override
public void onDestroy() {
...
EventBus.getInstance().unsubscribe(this, MyType.class);
}
#Override
public void newEvent(Object event) {
if (event instanceOf MyType) {
// do stuff
}
}
And then in your BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
EventBus.post(new MyType(true));
}
Example MyType
public class MyType {
public boolean networkEnabled;
public MyType(boolean networkEnabled) {
this.networkEnabled = networkEnabled;
}
}
This examples use the 2nd subscription utility (mine).