Android - How can I synchronize UsbManager::requestPermission? - java

I have the following code:
public final static #NonNull String ACTION_USB_PERMISSION = "blah blah";
public final #NonNull Object permissionLock = new Object();
public final #NonNull AtomicBoolean didReceiverReceive = new AtomicBoolean(false);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
didReceiverReceive.set(true);
synchronized (permissionLock) {
permissionLock.notifyAll();
}
}
}, new IntentFilter(ACTION_USB_PERMISSION));
final #NonNull UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
final #NonNull UsbDevice usbDevice = usbManager.getDeviceList().values().stream().findFirst().get();
// For the sake of requesting permission, assume
// usbDevice != null; (and unwrapping the Optional<UsbDevice> was successful)
// usbManager.hasPermission(usbDevice) == false;
// We need to request permission!
synchronized (permissionLock) {
usbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE));
/* CASE 1: assume UsbManager::requestPermission is asynchronous
* THIS CAUSES DEADLOCK! THIS IS BAD
try {
permissionLock.wait();
} catch (InterruptedException ie) {
// this never happens btw
throw new RuntimeException(ie);
}
*/
/* CASE 2: assume UsbManager::requestPermission is synchronous
* THIS THROWS AN ASSERTION ERROR! THIS IS BAD
assert didReceiverReceive.get();
*/
}
// TODO how do I safely block execution of the Thread that calls onCreate until the USB-permission broadcast receiver receives the broadcast intent?
}
I tried two things (named CASE 1 and CASE 2), which are in the onCreate method in the location in which they were invoked.
I was expecting that UsbManager::requestPermission was either asynchronous or synchronous. Pretty reasonable, no? It turns out it is semi-synchronous for lack of a better word. What happens is that the UsbManager seems to schedule the broadcast/permission request to be executed at some time in the future, but not necessarily on a different thread. This thread that it uses to schedule the broadcast/permission request is the same that calls onCreate, regardless of whether or not I put usbManager.requestPermission(...) in a new Thread. Consequently, I simply cannot create a scenario in which the USB-permission broadcast receiver's onReceive method is invoked appropriately before the onCreate method terminates.

Related

How to gracefully shut down all activities and close all running threads in an Android app?

At the moment, in each one of my activities I have this method:
private void registerReceiverClose(){
Activity activity = this;
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("CLOSE_ALL");
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activity.finish();
}
};
registerReceiver(broadcastReceiver, intentFilter);
}
and this one as well:
#Override
protected void onDestroy() {
unregisterReceiver(broadcastReceiver);
super.onDestroy();
}
They're triggered by the following logout button:
Button logout = findViewById(R.id.logout_button);
logout.setOnClickListener(click -> {
Intent intent = new Intent("CLOSE_ALL");
this.sendBroadcast(intent);
});
One thing that I'm sure is not closing in the right way, is that I have this code:
private static final ScheduledExecutorService pollingScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
private static final Object lock = new Object();
private static ScheduledFuture<?> currentRunningTask;
public void longPoll() {
synchronized (lock) {
if (currentRunningTask != null) {
currentRunningTask.cancel(true);
}
try {
currentRunningTask = pollingScheduledExecutor.scheduleAtFixedRate(this, 0, 3, TimeUnit.SECONDS);
} catch (Exception ignored) {
}
}
}
public void request() {
Thread requestThread = new Thread(this);
requestThread.start();
}
which continues to issue requests even after I think I should be logged out, which causes errors on the server.
How can I make sure all the threads stop gracefully and the application closes down in the right way?
You could wrapthe polling code inside of a Service. This service can then be stopped using
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
Inside of the service, you can override onDestroy() to clean resources up.

Updating Notification Continuously

Hello There I am a newbie for Android Development, working to learn it to my own!
I just want to update my notification in a Java Thread in my application (I am just learning and curious about how can I do it).
I have an activity, a simple thread to increment an Integer value. Then, I just want to show it in my Notification whenever the Integer value increments!
My Code is as:
public class MainActivity extends Activity{
private final String LOG_KEY = this.getClass().getSimpleName();
private int c = 0;
private boolean flag = true;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
builder = new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false);
builder.setOngoing(true);
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Thread t = new Thread(new MyThread());
t.start();
}//OnCreate ends
#Override
protected void onStop() {
super.onStop();
flag = false;
}//stop ends
#Override
protected void onDestroy() {
super.onDestroy();
flag = false;
}//destroy ends
private class MyThread implements Runnable {
#Override
public void run() {
while (flag) {
c+=1;
showNotification(Integer.toString(c) + " Counts");
}//while ends
}//run ends
private void showNotification(String msg) {
try {
//set the notification
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends
}//private class ends
}//MainActivity class ends here
As from my code, the notification appears and updates the value! But the problem is that it freezes the device and application at a sudden!
I just want help for what I am doing wrong as I am a newbie and learning it to my own. Any help and idea will be highly appreciated!
Thanks
You shouldn't be creating a notification and then continuously updating it as fast as you can from a thread. It's really not designed for that.
The closest thing I can think of that would meet your use case is using a notification to display progress. See this link:
Displaying Progress in a Notification
You might want to put some kind a rate limiter in your thread, unless you want your count to reach very high numbers very quickly. Perhaps make the thread sleep for a second between updates.
The problem is that you produce too much notifications more then a device can consume.
For your goal (just learn) you can add a some pause between notifications like that:
private void showNotification(String msg) {
try {
//set the notification
Thread.sleep(1000); //set the pause
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends

android run class in service with new thread

i just use service to make something like chathead and this is my result
but only i have two problem
first some time my service killed i notice that's on weak device so how can i prevent it from killed in same time the facebook messenger never killed
second my class animation not smooth i think i must run the class on new thread
xxx = new classanimation (mContext);
i tried this
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
xxx = new classanimation (mContext);
}
});
but i see it same no different
and this is my service code
public class MyCustomService extends Service {
private volatile HandlerThread mHandlerThread;
private ServiceHandler mServiceHandler;
private static Context mContext;
Handler mHandler;
IBinder mBinder = new LocalBinder();
public static Socket client;
public classanimation xxx;
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class LocalBinder extends Binder {
public MyCustomService getServerInstance() {
return MyCustomService.this;
}
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
// Define how to handle any incoming messages here
#Override
public void handleMessage(Message message) {
// ...
// When needed, stop the service with
// stopSelf();
}
}
public void onCreate() {
super.onCreate();
this.mContext = this;
xxx= new classanimation(mContext); //class i run it but its not smooth
mHandler = new Handler(Looper.getMainLooper());
// An Android handler thread internally operates on a looper.
mHandlerThread = new HandlerThread("MyCustomService.HandlerThread");
mHandlerThread.start();
// An Android service handler is a handler running on a specific background thread.
mServiceHandler = new ServiceHandler(mHandlerThread.getLooper());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Send empty message to background thread
mServiceHandler.sendEmptyMessageDelayed(0, 500);
// or run code in background
mServiceHandler.post(new Runnable() {
#Override
public void run() {
// Do something here in background!
SessionManager session = new SessionManager(mContext);
// If desired, stop the service
//stopSelf();
}
});
// Keep service around "sticky"
return START_STICKY;
}
#Override
public void onDestroy() {
// Cleanup service before destruction
mHandlerThread.quit();
}
}
To ensure that your service is never killed, you can make your service a foreground service by using a notifiaction. This means that there will always be a notification icon when the service is running, but it will never be killed. For example :
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
You can't prevent from killing,Yes but you can minimize probability of killing by starting service in different process than your app process.

launch/cancel activity immediatly when conditions are met in a service

So I'm building an application locker for android.Ive written a service for my locker activity to launch as soon as a particular activity is detected on top on the android application stack.The list of applications to be locked are stored in a table in a database.For the most part my service works fine.But I'm facing some issues which i do not know how to overcome. Any help is greatfully accepted
I want to resolve the following issues.
1) When i press the back button i want my locker activity and The app which was being to locked to stop executing. In my case,the lockeractivity keeps on launching again and again when i press the back button.
2) When a particular app which need to be be locked launches, the app is shown on the screen for a 1 second or 2 before my locker activity gets called.i want my locker activity to be invoked directly.
3) And some times my locker activity is called again once a user has already verified himself which is do not want. (i think this is cause of the timing of the service to check the foreground activity)
My Service
public class LockerService extends Service {
private static final String TAG = "MyService";
String LockedApps[];
String allowedapp = null;
DataBaseHandler handler;
private final static Handler servicehandler = new Handler() {
#Override
public void handleMessage(Message msg) {
}
};
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new DataBaseHandler(this);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private Runnable checkforeground = new Runnable() {
public void run() {
// / Any thing you want to do put the code here like web service
// procees it will run in ever 1 second
handler.open();
LockedApps = handler.getPackages();
handler.close();
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfo = am
.getRunningAppProcesses();
String foregroundapp = runningAppProcessInfo.get(0).processName
.toString();
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(LockerService.this);
allowedapp = sp.getString("allowedapp", "anon");
if ((Arrays.asList(LockedApps).contains(foregroundapp))
&& (allowedapp.equals(foregroundapp))) {
// do nothing
} else if (Arrays.asList(LockedApps).contains(foregroundapp)) {
// show your activity here on top of
// PACKAGE_NAME.ACTIVITY_NAME
Intent lockIntent = new Intent(getBaseContext(), Locker.class);
lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getBaseContext().startActivity(lockIntent);
}
servicehandler.postDelayed(this, 1500); // 1.5 seconds
}
};
#Override
public void onStart(Intent intent, int startId) {
servicehandler.removeCallbacks(checkforeground);
servicehandler.postDelayed(checkforeground, 1500);// 1.5 second
Log.d(TAG, "onStart");
}
}
Just Override onBackPressed() method in locker activity and fire a intent to the home launcher. that is nothing but it will takes you to the home screen.

How to set activity to be active all the time?

I have activity which needs to be active all the time. I have thread which sleep 10 sec, and monitors values taken from database, compare them and start method. I'm wondering if user go back to other applications and activities, does my activity and thread still work, or they are handled by activity manager and go to pause-stop-destroy?? How to stay them a live??
Thank you.
here is code for that thread:
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(10000);
myHendler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
final Calendar cal = Calendar.getInstance();
int godina2 = cal.get(Calendar.YEAR);
int mesec2 = cal.get(Calendar.MONTH);
int dan2 = cal.get(Calendar.DAY_OF_MONTH);
int sati2 = cal.get(Calendar.HOUR_OF_DAY);
int minuti2 = cal.get(Calendar.MINUTE);
trenutniDatum = new StringBuilder().append(dan2).append("-").append(mesec2 +1).append("-").append(godina2);
trenutnoVreme = prepraviVreme(sati2) + ":" + prepraviVreme(minuti2);
for(int i = 0; i < primljenoIzBazeDatum.length; i++){
String bazaBroj = "";
String bazaText = "";
if(primljenoIzBazeDatum[i].toString().equals(trenutniDatum.toString()) && primljenoIzBazeVreme[i].toString().equals(trenutnoVreme)){
int bazaId = Integer.parseInt(primljenoIzBazeId[i]);
bazaBroj = primljenoIzBazeBroj[i].toString();
bazaText = primljenoIzBazeText[i].toString();
String datumPromena = "*" + primljenoIzBazeDatum[i].toString() + "* SENT *";
datumVreme.open();
datumVreme.updateData(bazaId, datumPromena);
datumVreme.close();
sendPoruka(bazaBroj, bazaText);
}
} // end for
} // end run
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
Based on my understanding of what you want to do, here is what I would do :
First, create a BroadcastReceiver
public class Poller extends BroadcastReceiver {
private final String TAG = "Poller";
#Override
public void onReceive( Context context, Intent intent ) {
Log.i(TAG, "Poller broadcastintent received");
Intent myIntent = new Intent( context, PollerService.class );
context.startService( myIntent );
}
then , create the service that is called and then shuts itself down
public class PollerService extends Service {
final String TAG = "PollerService";
#Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "Service onStart()");
pollingTask.execute();
}
AsyncTask<Void, Void, Void> pollingTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... param) {
// Do what you want in the background
}
#Override
protected void onPostExecute(Void result) {
stopSelf();
}
};
}
then, set an AlarmManager to wake the service every minute
AlarmManager am = ( AlarmManager ) getSystemService( Context.ALARM_SERVICE );
Intent alarmIntent = new Intent( "CHECK_DATABASE" );
PendingIntent pi = PendingIntent.getBroadcast(context, 0 , alarmIntent, 0 );
int type = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long interval = POLLING_INTERVAL_IN_MILLISECONDS;
long triggerTime = SystemClock.elapsedRealtime() + interval;
// For short intervals setInexact repeating is same as exactRepeating, use at least fifteen minutes to make it more efficient
am.setInexactRepeating( type, triggerTime, interval, pi );
Log.i(TAG, "Set inexact alarm through AlarmManager");
}
setup the receiver in Android manifest
<receiver android:name="Poller">
<intent-filter>
<action android:name="CHECK_DATABASE"/>
</intent-filter>
</receiver>
finally, unset the AlarmManager to stop polling once your required SMS is received
AlarmManager am = ( AlarmManager ) getSystemService( Context.ALARM_SERVICE );
Intent intent = new Intent( "CHECK_DATABASE" );
PendingIntent pi = PendingIntent.getBroadcast( context, 0 , intent, 0 );
am.cancel(pi);
I do think that Peter is right though and this will kill you battery unless you'll only be checking until you get the required info and then don't poll and that's a short time.
Also, if you can get the exact time when you want to send the SMS with a single call from the database you can just set up the AlarmManger to wake up the service at that time, perform the action and be done with it. That would be the best approach (I can't quite make out if that is the case from you code but it does seems to be from you comments).
No, no application code on Android is not guaranteed to run all the time. Android OS can kill off aplications and services any time it feels it needs to.
Your best bet to periodically execute code would be to use AlarmManager, which makes your code execute periodically. Also a proper flag must be set to execute your code when device is asleep.
Note, since your period is very short (10s), it would keep CPU running all the time, draining the batterry very quickly.
If it has to be active all the time you have to use a Service: http://developer.android.com/guide/topics/fundamentals/services.html
I'm wondering if user go back to other applications and activities,
does my activity and thread still work, or they are handled by
activity manager and go to pause-stop-destroy?? How to stay them a
live??
They won't be kept "alive". If the system needs the resources your activity is destroyed. If you want to keep things running in the background even after your app is finished you have to use a Service.
In Java language you can scheduling your programs by traditional way:
java.util.Timer
java.util.TimerTask
for more information you can see:
http://enos.itcollege.ee/~jpoial/docs/tutorial/essential/threads/timer.html
http://www.ibm.com/developerworks/java/library/j-schedule/index.html
but better practice is using a scheduling framework such as Quartz, you can see http://www.quartz-scheduler.org/.
Spring framework also integration with Quartz framework.

Categories

Resources