I want to logout of the account whenever the user quits the application by holding the home button and swiping the app for it to close. Is there a function that runs whenever that happens?
I suggest you to override OnTrimMemory in Application:
#Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level == TRIM_MEMORY_UI_HIDDEN) {
doSomething();
}
}
Override onDestroy() or onStop()
public class YourApplication extends Application {
private Thread.UncaughtExceptionHandler androidDefaultUEH;
#Override
public void onCreate() {
super.onCreate();
androidDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(handler);
}
private Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable ex) {
Log.e("YourApplication", "Uncaught exception is: ", ex);
doSomething(); // Here your code have to come ..
androidDefaultUEH.uncaughtException(thread, ex);
}
};
In MANIFEST
<application
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:name=".YourApplication"
>
Related
I want to listen to accessibility gesture when user inside my app. It means onGusture should call when My App is at foreground but onGesture always called no matter my app at foreground or not. I try to set package name in Java as well as in XML but it's not working. Please take look at this tell me what I am doing wrong
MyAccessibilityService.java
public class MyAccessibilityService extends AccessibilityService {
private String TAG="MyAccessibilityServiceTAG";
#Override
protected boolean onGesture(int gestured) {//This method always called, I want this method only called when my App in foreground
Log.d(TAG,"onGesture:"+gestureId);
Toast.makeText(getApplicationContext(),"Gesture: "+gestureId,Toast.LENGTH_SHORT).show();
return super.onGesture(gestureId);
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
System.out.println("Event Occurred");
Log.d(TAG, "onAccessibilityEvent: event=" + event);
AccessibilityNodeInfo nodeInfo = event.getSource();
if (null == nodeInfo) return;
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
AccessibilityServiceInfo info = getServiceInfo();
// your other assignments
info.packageNames = new String[]{"com.vorail.ttsdemo"};
setServiceInfo(info);
}
#Override
public void onInterrupt() {
Log.d(TAG,"Accessibility Interrupted" );
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"Service Destroyed");
}
}
accessibility_service_config.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="#string/app_name"
android:accessibilityEventTypes="typeTouchExplorationGestureStart"
android:canRequestFilterKeyEvents="false"
android:accessibilityFeedbackType="feedbackSpoken"
android:packageNames="com.vorail.ttsdemo"
android:notificationTimeout="100"
android:settingsActivity="com.vorail.ttsdemo.MainActivity"
android:accessibilityFlags="flagDefault|flagRequestTouchExplorationMode"
android:canRequestTouchExplorationMode="true"
/>
By setting android:packageNames to something specific to your app, you'll filter the incoming events:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeViewClicked|typeViewFocused|typeTouchInteractionStart|typeTouchInteractionEnd|typeTouchExplorationGestureStart|typeTouchExplorationGestureEnd"
android:packageNames="com.app.yourapplication"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true" />
Im calling a fragment(ImageFraggment) from an actvity(MainActivity) , and created a interface on that fragment. And also i have implement Listner in Main activity. you can see the code below.
MainActivity.java
public class MainActivity extends AppCompatActivity implements ImageFragment.imageEventListener {
//Calling ImageFragment
#Override
public void eventListner(int number) {
log.d("MainActivity",number);
}
}
ImageFragment.java
public class ImageFragment extends Fragment {
private imageEventListener imageEventListener;
//enter a number
//if number equal to 1
{
imageEventListener.eventListner(number);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
imageEventListener = (imageEventListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement imageEventListener");
}
}
public interface imageEventListener {
void eventListner(int number);
}
}
This code works fine, means when user enters 1,log will display it(from mainActivity).
But now im trying to Listen to same event from another activity(AnotherActivity)(which doesnot call ImageFragment) as shown in below code.
AnotherActivity.java
public class AnotherActivity extends AppCompatActivity implements ImageFragment.imageEventListener {
//I dont call imageFragment here
#Override
public void eventListner(int number) {
log.d("AnotherActivity",number);
}
}
But im unable to print the number using log, How can i resolve this?I'm missng any major thing here?
At first, it will help you if you know the observer pattern: https://sourcemaking.com/design_patterns/observer
According to the observer pattern:
ImageFragment is a subject.
MainActivity and AnotherActivity are observers.
If you want to listen to an event from the subject, you need to register the observers first.
Look at your ImageFragment:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
imageEventListener = (imageEventListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement imageEventListener");
}
}
In here, you have registered only MainActivity(you said that: "which doesn't call ImageFragment"), for this reason, you will not able to listen to that event from that activity if you don't call/start that Imagefragment from that activity.
Thank you.
I have an Android App that has a class which runs a thread. Basically the same as here.
The thread at the moment updates a text-view with a calculated value every 500 ms and additionally logs the value, so I can see it in adb-logcat.
When I exit my Application with the back-button of the device, the thread still runs in the background. (Which is what I want). The adb-logcat still gives me the values, that the thread is calculating.
But when I reopen the application, the textview is not updated anymore!
What do I have to do, that it resumes updating the textview, when I open the app again?
Here is my simplified code:
SensorProcessor.java
public class SensorProcessor implements Runnable {
protected Context mContext;
protected Activity mActivity;
private volatile boolean running = true;
//Tag for Logging
private final String LOG_TAG = SensorProcessor.class.getSimpleName();
public SensorProcessor(Context mContext, Activity mActivity){
this.mContext = mContext;
this.mActivity = mActivity;
}
public void run() {
while (running){
try {
final String raw = getSensorValue();
mActivity.runOnUiThread(new Runnable() {
public void run() {
final TextView textfield_sensor_value;
textfield_sensor_value = (TextView) mActivity.findViewById(R.id.text_sensor);
textfield_sensor_value.setText("Sensor Value: " + raw); // <-------- Does not update the field, when app resumes
Log.v(LOG_TAG, raw); // <-------- Still working after the app resumes
}
});
Thread.sleep(100);
} catch (InterruptedException e) {
//When an interrupt is called, we set running to false, so the thread can exit nicely
running = false;
}
}
Log.v(LOG_TAG, "Sensor Thread finished");
}
}
MainActivity.java
public class MainActivity extends Activity implements OnClickListener, OnInitListener {
//Start the Thread, when the button is clicked
public void onClick(View v) {
if (v.getId() == R.id.button_start) {
runnable = new SensorProcessor(this.getApplicationContext(),this);
thread = new Thread(runnable);
thread.start();
}
}
You can extend Application class and insert there getter and setter method to your Runnable. Here is example of MyApplication (don't forget to add the manifest connection!), in manifest.xml:
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppBaseTheme" >
Then MyApplication:
public class MyApplication extends Application {
private SensorProcessor mSensorProcessor = null;
public SensorProcessor getCurrentSensorProcessor(){
return mSensorProcessor;
}
public void setSensorProcessor(SensorProcessor mSensorProcessor){
this.mSensorProcessor = mSensorProcessor;
}
}
Inside onCreate() of your activity by call :
((MyApplication)getApplication()).getCurrentSensorProcessor().mActivity = this;
you need also to modify the Runnable constructor:
public SensorProcessor(Context mContext, Activity mActivity){
this.mContext = mContext;
this.mActivity = mActivity;
((MyApplication)mActivity.getApplication()).setSensorProcessor(this);
}
And don't forget to empty the instance of mSensorProcessor by calling this inside the Runnable when finish :
((MyApplication)mActivity.getApplication()).setSensorProcessor(null);
Finally you need to modify onClick in your Activity:
if (v.getId() == R.id.button_start) {
SensorProcessor mSensorProcessor = ((MyApplication)getApplication()).getCurrentSensorProcessor();
if (mSensorProcessor != null)
mSensorProcessor.mActivity = this;
else {
runnable = new SensorProcessor(this.getApplicationContext(), this);
thread = new Thread(runnable);
thread.start();
}
}
It should work, maybe by some minor changes.
I am wondering how to check if my application is open and currently visible to the user when receiving an onMessage() from GCM. At first, I was just using my own boolean isVisible, but then I realized this isn't reliable, because if the app isn't open, the object I use to access that flag is null. While this in itself could be used to see if the app is open, it seems a little bit messy. Is there a way in Android from a system level to somehow check if the application is currently open, and if the user is viewing the app? Keep in mind an app could technically be running, but not be visible, because a user has recently pressed the "home" button sending it to the background.
#Override
protected void onMessage(Context arg0, Intent arg1) {
String turn = intent.getExtras().getString("turn");
if (turn.equals("yours"){
if (/*app is open*/){ <------------------ what can go here?
// dont generate a notification
// display something in the game instead
}
else{
// generate notification telling player its their turn
}
}
}
I would use order broadcasts to do that.
In your onMessage method:
Intent responseIntent = new Intent("com.yourpackage.GOT_PUSH");
sendOrderedBroadcast(responseIntent, null);
In your Activity:
public class YourActivity extends Activity {
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Right here do what you want in your activity
abortBroadcast();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//.....
}
#Override
protected void onPause() {
unregisterReceiver(mBroadcastReceiver);
super.onPause();
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter("com.yourpackage.GOT_PUSH");
filter.setPriority(2);
registerReceiver(mBroadcastReceiver, filter);
super.onResume();
}
}
The other BroadcastReceiver
public class SecondReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//In this receiver just send your notification
}
}
Manifest:
<activity
android:name=".YourActivity"
android:label="#string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SecondReceiver">
<intent-filter
android:priority="1">
<action
android:name="com.yourpackage.GOT_PUSH" />
</intent-filter>
</receiver>
Basically in the onMessage method you send an Intent which is first received by the BroadcastReceiver registered inside YourActivity if it is running and in foreground, otherwise it is received by the SecondReceiver.
Use SharedPreferences saving the boolean isVisible, and when you get the value from the preference you can add a default value.
SharedPreferences settings = context.getSharedPreferences("NAME_XXX", Activity.MODE_PRIVATE);
settings.getBoolean("visible", false);
What I always do is have a reference to the current Activity.
I set the current Activity in every onResume to this and set it to null in every onPause.
If the current Activity is null then the app is not open. If it's not null you can see if the correct Activity is open and deliver it to that Activity.
GCMIntentService:
public static Activity currentActivity;
public static final Object CURRENTACTIVIYLOCK = new Object();
#Override
protected void onHandleIntent(Intent intent) {
synchronized(CURRENTACTIVIYLOCK) {
if (currentActivity != null) {
if (currentActivity.getClass() == CorrectActivity.class) {
CorrectActivity act = (CorrectActivity)currentActivity;
act.runOnUiThread(new Runnable() {
public void run() {
// Notifiy activity
}
});
} else {
// show notification ?
}
} else {
// show notification
}
}
}
CorrectActivity:
#Override
protected void onResume() {
synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
GCMIntentService.currentActivity = this;
}
}
super.onResume();
}
#Override
protected void onPause() {
synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
GCMIntentService.currentActivity = null;
}
super.onPause();
}
The thing that worked for me:
Create a final Class Constants, inside it, create static varaiable:
public final class Constants{
public static AppCompatActivity mCurrentActivity;
}
Now, on each on resume of your activties say:
#Override
protected void onResume() {
super.onResume();
Constants.mCurrentActivity = this;
}
When receieving notification, check if current activity is null, if its null, application is not opened, if activity isn't null, you can check things like:
if(Constants.mCurrentActivity instanceof MainActivity){
((MainActivity) Constants.mCurrentActivity).yourPublicMethodOrStaticObject;
}
Need your help!
How do I in my application to call the function only once when opening?
I do:
private boolean is_first = true;
#Override
public void onCreate(Bundle savedInstanceState) {
if ( is_first ) {
MyFirstFunction();
}
}
public void onResume(Bundle savedInstanceState) {
super.onResume();
is_first = false;
}
Also in the manifest file added to the activity android:configChanges="orientation" but still function when you turn the device restarts
I hope for your help!
you can use Application class to do that in the onCreate method you can call your function
public class MyApp extends Application {
#Override
public void onCreate() {
//this will be called each time you open the application
super.onCreate();
//call you function here
}
}
then add this class to the manifest
<application
android:name=".MyApp or your class name"
......
....>