Locking the device with AccessibilityService and TileService - android

I have simple example of an app that perform the locking via GLOBAL_ACTION_LOCK_SCREEN (new feature from Pie).
In that example are:
1) AccessibilityService.class as follow:
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
doLock();
}
}
public void doLock() {
performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN);
}
2) TileService.class as follow:
#Override
public void onStartListening() {
super.onStartListening();
Tile t = getQsTile();
t.setState(Tile.STATE_INACTIVE);
t.updateTile();
}
#Override
public void onClick() {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK);
startActivityAndCollapse(i);
super.onClick();
}
3) MainActivity.class as follow:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
MainActivity.this.finish();
}
}, 2500);
Now I have question about implementation exactly the same app without MainActivity. How to call AccessibilityService's method doLock() directly from TileService's onClick Method?
I've tried with no luck Messenger, EventBus, etc.
Is there any possibility to do it - just click on QS tile and directly call method DoLock (or maybe through onAccessibilityEvent, but I don't know what is event fired in that case)?
Thanks in advice.
P.S. Sorry if my question too stupid for you, I'm really new in Android development.
P.S2 Really appreciate if someone give me some code example, not just hints.

Related

Update Activity UI from a Timer , after restarting Activity

In the onCreate() method of my activity I have a Timer + TimerTask that will schedule a ParseQuery. On The ParseQuery callback, which is on mainThread, I delegate an interface callback to make a simple UI update. This works when I let the Activity unchanged. But if I exit from the activity and enter again it (A new timer will NOT be created here, because it gets created only when starting the activity from a certain point) wouldn't work. I think is something with Activity instances but I cannot handle it.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
....
uiTimer = new Timer();
uiTask = new TimerTask() {
#Override
public void run() {
doParseTask();
}
};
uiTimer.schedule(uiTask, shortCodeLeft);
}
doParseTask(){
Utils.doParseQuery(this, new MyListener{
#Override
public void onSuccess() {
updateUI();
}
});
}
updateUI(){
Log.i(TAG, "Show changed layout"); //This is always shown, this way I ensure it gets here!!
mTextView.setText(foo); //this doesn't work
mLayout.setVisibility(View.GONE); //this doesn't work
}
The ParseQuery is executed in done() callback method, I call the function that updates the UI:
public class Utils{
.......
doParseQuery(Context ctx, MyListener listener){
.......
query.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e == null){
....
listener.onSuccess();
}
}
});
}
}
What I have tried, with no success:
1. make the `uiTimer` and `uiTask` static global variables; // I thought that maybe it gets leaked into activity instances
2. update the UI using
runOnUiThread(new Runnable() {
#Override
public void run() {}
});
OR
mLayout.post(new Runnable() {
#Override
public void run() {
mLayout.setVisibility(View.GONE);
}
});
3. android:launchMode= "singleInstance" //in Manifest
If you want that your UITimer to gets executed every time your activity goes to foreground, you should implement the onStart or onResume method and move your uiTimer implementation to one of both method. Even your activity being already started these two methods are called after exiting the activity and reopening it again.
A better explanation of Android Activity lifecycle is well explained by google documentation https://developer.android.com/guide/components/activities/activity-lifecycle.html.
Your code would look like this:
#Override
protected void onStart() {
super.onStart();
....
uiTimer = new Timer();
uiTask = new TimerTask() {
#Override
public void run() {
doParseTask();
}
};
uiTimer.schedule(uiTask, shortCodeLeft);
}
doParseTask(){
Utils.doParseQuery(this, new MyListener{
#Override
public void onSuccess() {
updateUI();
}
});
}
When you exit from your activity, the instances mTextView and mLayout will be destroyed.
Then, when you create a new activity, the activity creates new instances of the text view and layout.
Your timer goes off and tries to update the original elements, which are now invalid as the activity has been closed (but the log still works as this is separate to your activity).
You should initialise the timer & task in onCreate(), and then in order to stop updating the old UI elements:
#Override
protected void onStop() {
if (uiTimer != null) {
uiTimer.cancel();
}
super.onStop();
}

Android - Stop Activity when boolean changed

I've built an app that has this activities LifeCycle:
StartActivity -> TemplateChooseOptions -> ChooseTemplate -> Templates
and i have a class that has boolean in it. the boolean will change when a server error is occurred.
when the boolean change, i want that all the activities will finish exept for Start Activity.
I've tried this:
new Thread(new Runnable() {
public void run() {
ClientLogic CL = Globals.getInstance().getCL();
while(!CL.isErrStatus());
if(CL.isErrStatus()){
finish();
}
}
}).start();
but it takes too much CPU power.
what can I do?
Don't use a thread, create your own listener and implement it in your activities
public class MainActivity extends Activity implements ServerErrorListener {
#Override
onServerError() {
finish();
}
#Override
protected void onResume() {
if(ClientLogic.getInstance().getCL().isErrStatus) {
// Todo finish
}
ClientLogic.getInstance().addErrorListener(this);
}
#Override
protected void onPause() {
ClientLogic.getInstance().removeListener(this);
super.onPause();
}
}
Or use a BroadcastReceiver as #mubeen says.

How to press physical buttons of android programatically

I want to press volume button programatically. In Java it is possible using the robot class, but in Android there is no robot class.
I am wondering how to achieve this in Android.
I would suggest you to increase/decrease the volume programmatically which would be a tad bit easier, however if you want to use it for some other process then you can check the code below -
EDIT - The snippet I gave before doesn't work, but this one does. It uses a runnable so the try catch block is necessary.
new Thread(new Runnable() {
#Override
public void run() {
try {
Instrumentation inst = new Instrumentation();
//This is for Volume Down, change to
//KEYCODE_VOLUME_UP for Volume Up.
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_VOLUME_DOWN);
}catch(InterruptedException e){}
}
}).start();
how about this
private abstract class SimpleButton extends Button {
public SimpleButton(String text) {
super(TechDemoLauncher.this);
setText(text);
setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onButtonPressed();
}
});
}
public abstract void onButtonPressed();
}
after that you can just implement the onButtonPressed() method like this
private void Example(String string) {
yourLayout.addView(new SimpleButton(string) {
#Override
public void onButtonPressed() {
//insert your code
}
});
}

How do I know if my app has been minimized?

Activity.onPause() and onStop() are called in (at least) two situations:
The another Activity was launched on top of the current one.
The app was minimized.
Is there an easy way to tell the difference?
You could do it this way. Make all of your activities extend from a base activity. The base activity needs to keep a visibility counter that is incremented/decremented during onResume/onPause:
public abstract class MyBaseActivity extends ActionBarActivity {
private static int visibility = 0;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
visibility++;
handler.removeCallBacks(pauseAppRunnable);
}
#Override
protected void onPause() {
super.onPause();
visibility--;
handler.removeCallBacks(pauseAppRunnable);
// give a short delay here to account for the overhead of starting
// a new activity. Might have to tune this a bit (not tested).
handler.postDelayed(pauseAppRunnable, 100L);
}
#Override
protected void onDestroy() {
super.onDestroy();
// uncomment this if you want the app to NOT respond to invisibility
// if the user backed out of all open activities.
//handler.removeCallBacks(pauseAppRunnable);
}
private Runnable pauseAppRunnable = new Runnable() {
#Override
public void run() {
if (visibility == 0) {
// do something about it
}
}
};
}

Failed stop, Android app with TarsosDSP

I want to implement an android app using TarsosDSP package on this link:
https://github.com/srubin/TarsosDSP/releases/tag/TarsosDSPAndroid-v3-MAD
I created two buttons for startRecording and stopRecording, my app does "start" but doesnn't "stop". My MainActivity is this:
public class MainActivity extends ActionBarActivity {
private Button start;
private Button stop;
MicrophoneAudioDispatcher audioDispatcher = new MicrophoneAudioDispatcher(44100, 2048, 1024);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setButtonHandlers();
start = (Button) findViewById(R.id.btStart);
stop = (Button) findViewById(R.id.btStop);
}
private void setButtonHandlers() {
((Button)findViewById(R.id.btStart)).setOnClickListener(btnClick);
((Button)findViewById(R.id.btStop)).setOnClickListener(btnClick);
}
private void startRecording() {
audioDispatcher.run();
}
private void stopRecording() {
audioDispatcher.stop();
}
private View.OnClickListener btnClick = new View.OnClickListener() {
public void onClick(View v) {
switch(v.getId()){
case R.id.btStart:{
startRecording();
break;
}
case R.id.btStop:{
stopRecording();
break;
}
}
};
};
}
The class "MicrophoneAudioDispatcher" is on this link:
https://github.com/srubin/TarsosDSP/blob/master/src/be/hogent/tarsos/dsp/MicrophoneAudioDispatcher.java
I don't understand this error. Can someone help me?
Thanks in advance.
You have to initial a thread for AudioDispatcher instead to call AudioDispatcher.run() directly.
dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(22050, 1024, 0);
dispatcher.addAudioProcessor(new PitchProcessor(PitchProcessor.PitchEstimationAlgorithm.FFT_YIN, 22050, 1024, new PitchDetectionHandler() {
#Override
public void handlePitch(PitchDetectionResult pitchDetectionResult,
AudioEvent audioEvent) {
final float pitchInHz = pitchDetectionResult.getPitch();
runOnUiThread(new Runnable() {
#Override
public void run() {
mFrequencyView.setText(String.valueOf(pitchInHz));
}
});
}
}));
new Thread(dispatcher, "Audio Dispatcher").start();
The thread will keep running until you call AudioDispatcher.stop(). It is important to avoid the thread remains on background.
#Override
protected void onPause() {
super.onPause();
dispatcher.stop();
}
First of all, the link you mentioned (TarsosDSPAndroid-v3-MAD) is a TarsosDSP fork that is compatible with Android. Since some time it isn't needed anymore, as described on official site:
the fork of TarsosDSP kindly provided by GitHub user srubin, created for a programming assignment at UC Berkley, is not needed any more.
And what relates to your main question, you shouldn't manually call run() of AudioDispatcher, it should be called from separate thread like mentioned in the link above, something like this:
new Thread(dispatcher,"Audio Dispatcher").start();

Categories

Resources