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" />
Related
I currently have an app setup to receive remote notifications using Azure Notification Hub.
Now, I would like to scan for iBeacons, see if a specific one is close by and if so, the notification should not be shown to the user. However, if the beacon isn't in sight, the user should receive this notification.
Basically I want the beacon to supress the notifications for this app.
How would one go about doing this?
Based on the docs from Azure, when a remote notification comes in, you get a callback like this:
public class MyHandler extends NotificationsHandler {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Context ctx;
#Override
public void onReceive(Context context, Bundle bundle) {
ctx = context;
String nhMessage = bundle.getString("message");
sendNotification(nhMessage);
if (MainActivity.isVisible) {
MainActivity.mainActivity.ToastNotify(nhMessage);
}
}
private void sendNotification(String msg) {
// put your notification code here
...
}
}
If you want to filter the notifications based on what beacons are present, you can add that logic to the onReceive method like this:
public void onReceive(Context context, Bundle bundle) {
if (!(MyApplication)this.getApplication()).isBeaconVisible()) {
// Suppress notification by returning early from method
return;
}
...
}
The above isBeaconVisible() could be implemented in a custom Android Application class using the Android Beacon Library with something like below. You'll need to read more about how to set up that library to make this work. You'll also need to register the custom Application class in your AndroidManifest.xml.
public class MyApplication extends Application implements BeaconConsumer, RangeNotifier {
public Collection<Beacon> mVisibleBeacons;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
// TODO: look up the proper I_BEACON_LAYOUT in a google search
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(I_BEACON_LAYOUT));
beaconManager.addRangeNotifier(this);
}
#Override
public void onBeaconServiceConnect() {
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
try {
beaconManager.startRangingBeaconsInRegion(new Region("all-beacons", null, null, null));
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
mVisibleBeacons = beacons;
}
public boolean isBeaconVisible() {
return mVisibleBeacons.size() > 0;
}
}
The above logic for isBeaconVisible() returns true if any beacon with any identifier has been seen in the last second. But you can alter this to make it more sophisticated per your requirements.
You can use some opensource library to work with beacons. I used Altbeacon library for example.
Here is the samples : https://altbeacon.github.io/android-beacon-library/samples.html
For your target you need to implement BeaconConsumer interface on Activity or Service. It has a method onBeaconServiceConnect(). Example of implementation:
#Override
public void onBeaconServiceConnect() {
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() == 0) {
Log.i(TAG, "Show your notification here");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("someRangingUniqueId", null, null, null));
} catch (RemoteException e) { }
}
I am trying to make a speech powered app, however I have run into a major problem.
My UtteranceProgressListener Class will not call any of the given methods regardless of where I place the Speak method.
Here is my code:
This is my OnCreate Method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
voiceBtn = (Button) findViewById(R.id.startListeningBtn);
voiceBtn.setEnabled(false);
textToSpeech = new TextToSpeech(mContext,new botListener());
}
This is the OnInitListner Imeplementation
public class botListener implements TextToSpeech.OnInitListener{
#Override
public void onInit(int i) {
if(i == TextToSpeech.SUCCESS)
{
int s = textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String s) {
Toast.makeText(getApplicationContext(),"Done Speaking",Toast.LENGTH_SHORT).show();
}
#Override
public void onDone(String s) {
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
}
#Override
public void onError(String s) {
Toast.makeText(getApplicationContext(),"Done Speaking",Toast.LENGTH_SHORT).show();
}
});
Log.d(TAG,String.valueOf(s));
int result = textToSpeech.setLanguage(Locale.ENGLISH);
if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED){
Log.e(TAG,"Language not supported");
Intent installLanguage = new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installLanguage);
}
Log.d(TAG,"Started Voice Speaker");
}
else{
Log.e(TAG,"initialization failed");
}
}
}
Now, when I press the button, the event that fires is:
public void initVoiceRecog(View v){
//Toast.makeText(mContext,"Clicked",Toast.LENGTH_SHORT).show();
Speak("hello","1");
// does some other things here after that
}
private void Speak(String text,String identifierID){
if(Build.VERSION.SDK_INT>21) {
Bundle params = new Bundle();
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,identifierID);
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, params, identifierID);
}
else{
// ttsMap is a HashMap
ttsMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,identifierID);
textToSpeech.speak(text,TextToSpeech.QUEUE_FLUSH,ttsMap );
}
}
My Question is, after saying hello, it does not fire the OnStart() or the OnError() or the OnDone() methods. Why is this happening?
I tried with the deprecated setOnUtteranceListner() as well, same result. It does not fire any of the methods, the Toasts don't show up.
Please tell a fix or a workaround for this.
The Devices I tried on are:
API 19 Micromax Canvas Nitro
API 21 Samsung S4
API 23(Marshmellow) ASUS Zenfone
I finally figured out why the callbacks were not working. Turns out, they were working and calling on a separate thread. So to execute the normal functionality, call the functions in the 'Activity.this.RunOnUiThread' and put this in the call back fuctions.
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"
>
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"
......
....>