How to observe a collection from android foreground (vpn)service - android

I have a singleton class with the "block/allow logic" for my VPN tunnel. Packets sent into the tunnel are not emitted, applications are allowed to bypass based on an allowance list, therefore it can behave as a simple implementation of a firewall.
What I want to do is, when I change the Set<String> of blocked application packagenames, I would like the service thread to run vpnservice.builder.establish() again, using this blocked application set.
An obvious choice for this - in case an "ordinary" foreground service if the service extends LifecycleService, as shown here. However, my service has to extend android.net.VpnService, which does not implement LifecycleOwner. A possible implementation (with some modifications needed) is shown here.
My questions are:
Is there a better, cleaner, more elegant way for my VPN service to observe changes in my blockedPackageName Collection, in my singleton class?
If there is not another way, will implementing LifecycleOwner work in the way I expect it (how I described it, basically)?
If(2), is it enough to add lifecycle.handleLifecycleEvent(Lifecycle.Event.XXXX); in my service's onCreate and onDestroy methods (see below)? Do these do anything apart from preventing memory leaks?
//MyVpnService class
#Override
public void onDestroy() {
Log.i(TAG, "Destroyed.");
stopVpn();
//what is the purpose of this line for my goals?
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
P.S.: I read the official documentation with regards to Lifecycle components, but I could not find enough code examples for my cases to make the matter more clear.

The best solution I find was to send a broadcast with a custom intent from the singleton class, and signing up a broadcast receiver for this intent in the vpnservice class on start.
For sending a broadcast from any class, you need context - lucky for me, I already needed context in my singleton, for which context.getApplicationContext() works fine without leaking.

Related

Activity, Service and what kind of communication between?

I'm trying to develop an Android application consists of an Activity and a Service. The Activity launch a process on the Service of indefinite duration, which will be closed from Activity. Do not use then the subclass IntentService, but directly Service. Controlled by onStartCommand and OnDestroy.
I obviously need to pass information from the Activity to the Service: the status of the Service and some strings.
I tried to use LocalBrodcastManager, but when turning the devices or when the activity goes in state onPause, the message will lost. I tried to follow several examples, but with little success. This in particular I could not complete it because of some missing information, evidently deemed obvious, but which are not obvious to me: https://developer.android.com/training/run-background-service/report-status.html
I then tried to use Messenger via IBinder ( Example: Communication between Activity and Service using Messaging ), But the program seems a bit complex and I can not able to fit my needs.
What I need is to launch the service from my activity (possibly make binding automatically?, in case of Messenger use), the Service should signal the Activity to be active, then Service records some points via GPS LocationListener, writes it to a file and should point out, again the Activity, the data that is recording, the file size, etc.
What do you recommend to use to pass this information and can you provide to me some example?
I am actually in the midst of a tutorial explaining and comparing many different approaches to IPC in Android but since it's not ready and because you need an easy fix i'll recommend https://github.com/greenrobot/EventBus.
Also feel free to look in an old but still relevant example me and my friends made a while back here: https://github.com/RanNachmany/AndconLab
Goodluck.

Do I need to release LocalBroadcastManager that is gotten from LocalBroadcastManager.getInstance?

http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html does not include a release method. Does it mean it will be GC-ed automatically? Thanks.
LocalBroadcastManager does not include a release method. Does it mean it will be GC-ed automatically?
No it will not. But it also does not have to.
It will exist from the point in time you fist call that method anywhere in your app until your app process is killed.
A static method named getInstance that returns you an instance of the class it is in, means in most cases that you're dealing with a singleton.
Singletons are objects that are intended to exist only once in your entire app and they behave like global variables (that is often considered bad for several reasons).
The whole broadcast mechanism would break down if the place in your code that register to receive broadcasts would use a different broadcast manager than the one the broadcasts are send over. The code makes sure that everybody uses the same one by making it a singleton.
LocalBroadcastManager will on the other hand not leak your activity context if you take that as parameter. It will call context.getApplicationContext() to get the application context which is itself a singleton that is safe to keep referenced forever.
The way the code creates the singleton and how to deal with context in singletons is described in further details in this article: Context, What Context? (Note: in a threadsafe way - unfortunately missing in that article)

Android Activity Recognition with listener or broadcast receiver?

I'm wondering, why ActivityRecognitionClient has no method to request updates with standard java listener as parameter? More strange, that in the same time, LocationСlient has such method and it works good.
Official example for Activity Recognition looks terrible. A lot of coupled and boilerplate code. It looks like IntentService is sole variant for handling updates from ActivityRecognitionClient. It's extremely uncomfortable.
#Guys from Android Team, why it happens?
As Developer I hope to see requestActivityUpdates(interval, listener) method in next version of Google Play Services.
For now, does anyone know, is it possible to use BroadcastReceiver for handling updates from ActivityRecognitionClient?
I'm wondering, why ActivityRecognitionClient has no method to request updates with standard java listener as parameter?
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.
Beyond that, quoting the documentation for requestActivityUpdates():
A common use case is that an application wants to monitor activities in the background and perform an action when a specific activity is detected. To do this without needing a service that is always on in the background consuming resources, detected activities are delivered via an intent. The application specifies a PendingIntent callback (typically an IntentService) which will be called when activities are detected.
It looks like IntentService is sole variant for handling updates from ActivityRecognitionClient.
It's not.
For now, does anyone know, is it possible to use BroadcastReceiver for handling updates from ActivityRecognitionClient?
There are several types of PendingIntent, created from various factory methods. The sample shows using getService() to create a PendingIntent that will call startService(). You are welcome to use any other PendingIntent, such as one from getBroadcast(), which will call sendBroadcast().

Android remote service callbacks

(I have a remote service with an AIDL interface that is used by several client apps. I would like to add an asynchronous method to the interface for calls that take some time, but I need the solution to be secure, meaning that only my applications can communicate with the service. The client applications are signed with the same signature as the service app. Currently the apps just bind to the service and call a single interface method to perform various operations.
One option is broadcasting an Intent from the service when the operation is complete and using a BroadcastReceiver in the client application, but (Question #1) can this be done in a way that ensures only my apps can receive the Intent? setPackage() seems to do this, but I need to support Gingerbread devices, which seems to rule out that approach according to the answer here: setPackage for intent in gingerbread
So it seems I need to add a second .aidl interface with the callback interface for the service to use, implemented by the client. I have seen examples that use listeners here, but I am not sure what the difference is versus the client just passing in the second interface object as an argument (as used in the IScript / IScriptResult example from this answer: Service call backs to activity in android)
Question #2, what is the benefit of using a listener here vs. a callback method?
A callback method/listener is the right thing to do. (As CommonsWare says, it's pretty much the same thing). I would say it's much simpler than fiddling around with BroadcastReceivers, since you're already using aidl.
Something like this:
IAsyncThing.aidl:
package com.my.thingy;
import com.my.thingy.IAsyncThingListener;
interface IAsyncThing {
void doSomething(IAsyncThingListener listener);
}
IAsyncThingListener.aidl:
package com.my.thingy;
import com.my.thingy.IAsyncThingListener;
interface IAsyncThingListener {
void onAsyncThingDone(int resultCodeIfYouLike);
}
You can enforce that only your apps can bind to the service by using a signature-level permission on your service (see the note on 'service permissions' here: http://developer.android.com/guide/topics/security/permissions.html). Specifically:
Declare a permission in your service's AndroidManifest.xml. Ensure it is signature level.
Add that permission in your service tag
In all the other apps, use uses-permission to use it.
A couple of other things to bear in mind:
In the caller, you'll need to subclass IAsyncThingListener.Stub. Your calling application code may already be subclassing something else, so that means you'd have to use an extra (probably inner) class to receive the completion notification. I mention this only because this might be the answer to question #2 - which I don't fully understand.
If the service is potentially in different processes from the caller, each should register for death notification of the other using IBinder.linkToDeath.

Android: Singleton which is used between Activity and Service

im wondering if it would be a bad idea to create a Singleton that is used between some Android Activities and a Android Service. As far as I know the static fields, in my case the Singleton, is available as long as the whole Process is alive.
My plan is to use a singleton instead of Parcelable to share data between my activities and a Background service. So my Activity1 will add some data by calling MySingleton.getInstance().addData(foo); then I would sent an Intent to inform my Service that new Data has been added to the singleton. Next my BackgroundService would handle the intent and call MySingleton.getInstance().getLatestData(); then it would process the data (takes some time). The result of the service would next be "post" back by using the singleton and fire a broadcast intent, which are handled by the Activity1 (if alive) and the Activity1 will retrieve the result from the singleton.
Do you guys think thats a bad idea?
EDIT:
What I want to implement is an peace of software that downloads data from a web server parse it and return the result. So my Activity would create DownloadJob Object. The DownloadJob-Object would be put into the DownloadScheduler (Singleton) which queues and manage all DownloadJobs. The DownloadScheduler would allow to run 5 DownloadJobs at the same time and use a queue to store the waiting. The effective Download would be done by the DownloadService (IntentService), which gets informed over an Intent that the a new DownloadJob should now be executed (downloaded) right now. The DowanlodService would retrieve the next job from the DownloadSchedulers queue (PriorityBlockingQueue) and return the Result by setting DownloadJob.setResult(...) and fires up an broadcast intent, that the Result is ready, which will be received by the DownloadScheduler which would remve the job from the queue and inform the Activity that the download is complete etc.
So in my scenario I would use the singleton to access the DownloadJobs from the DownloadService instead of making a DownloadJob Parcelable and pass it with the Intent. So i would avoid the problem, that I have two DownloadJobs in memory (one on the "Activity Site" and one on "Service site").
Any suggestions how to solve this better?
Is it true that static instances, like DownloadScheduler(Singleton), would be used by freed by the android system on low memory? So would subclassing the Application and hold there the reference (non static) avoid this problem?
If you are using the singleton just as shared memory between a background service which I assume is performing operations on a different thread, you may run into synchronization issues and or read inconsistent data.
If the data in the singleton is not synchronized, you have to be careful because you are relying on your "protocol" to be sure that nobody is reading while your background thread is writing (which may lead to errors).
On the other hand, if it is synchronized, you are risking to face anr error because the activity which reads the data may be blocked waiting the service to finish to write the data in the singleton.
As the other said, you also have to keep in mind that your singleton may be freed if the os needs resources, and that your data may not be there anymore.
I'd rather use an event bus such as otto or eventbus
EDIT:
Using a singleton as the entry point of background (intent) service is the approach suggested in 2010 Virgil Dobjanschi talk about building rest client applications for android.
The suggested approach is having a singleton that performs as controller of ongoing requests. Please consider also that request to intent service are already queued by the os, so you can throw several intents that will be processed sequentially by the intent service.
Some time ago I also tried take that as a starting point for a library, which still remains unfinished. YOu can find the sources here
What I would certainly not do is to store your data in the singleton. The approach I would prefer is to store the data in some persistent storage (such as sql / preferences / file / content provider) and let the client know of the change through a broadcast message (or, if you are using a content provider, through an observer).
Finally, to some extent this is the approach followed by the robospice library, which looks quite mature and ships a lot of interesting features such as caching.
A better idea is to subclass Application and put any long living objects in there. By subclassing Application you can properly handle startup and shutdown of the application something you can't easily do with a singleton. Also by using an Application Activites and Services can share access to the models within your program without resorting to parcelables. And you can avoid all of the problems Singletons bring to your program.
You also don't have to resort to storing everything in a database which requires lots of boiler plate code just to shove a bunch of data in there. It doesn't do anything for sharing behavior between parts of your application and doesn't do anything to facilitate communication and centralization of activities. If you really need to persist state between shutdowns great use it, but if not you can save yourself a lot of work.
You could also look into using something like Roboguice which makes injecting shared models into your Activities and services.
You might find this helpful:
what's design pattern principle in the Android development?
Using a singleton like this is not necessarily a bad idea, but you will lose it's state if Android decides to stop your process. You may want to consider storing your state instead in a SQLite database or a persistent queue (take a look at tape for a good example).

Categories

Resources