I'm writing an app that makes use of the fileobserver in android. When I file is modified in anyway (creation, etc.) it should upload. In order to implement a queue and keep from running out of memory by using threads and such, I want to use an IntentService to upload the files one at a time, and keep from executing when it fails so that when the user regains connectivity, it uploads. But here is the problem:
All of the given constructors for Intent...
Intent();
Intent(Intent );
Intent(String );
Intent(Context, Class<?>); //The one I always use
Intent(String, Uri );
Intent(String, Uri, Context, Class<?> );
...wont work. Because I'm working in an extension of FileObserver, there is no acceptable context from which I can feed the Intent. Is there anyway I can use just the String one to start the IntentService? I don't need it to return anything, I just need to feed it a few strings for it to work (filename, etc.) Or is there another way I can start the IntentService. This one's really got me stumped.
Thanks for any help in advanced!
Edit: Alright. I've tried many contexts but none see to work. The intent service isn't being fired by application or base contexts from the service class being passed through the constructors as they're called. Here is the basic layout of my app:
Login Activity goes to Menu Activity, Menu Activity starts Service, Service Starts Service Handler (see the example of a service in the android docs to see what it is) and passes the context through the constructor. Service Handler starts FileSync and passes context through the constructor. FileSync holds onto the context in a class variable. FileSync then waits until a file is modified and then uses the context to start the IntentService to upload the file requested through the Intent. I know it's really complicated, but it's really the only way I can do it at the moment.
Because I'm working in an extension of FileObserver, there is no acceptable context from which I can feed the Intent.
This FileObserver cannot exist in a vacuum. It needs to be managed by an activity or service, and that will give you your Context.
You can create a static field of you Application by overriding Application. In oncreate
sInstance = this;
Use
MyApplication.sInstance.startActivity(intent);
Edit:
On second thought you could use PendingIntent if all you need to do is start a service without passing any information from FileObservver, you can create a PendingIntent and set it at the time of creation of FileObserver and use
pendingintent.send()
Related
I've custom JobIntentService witn static method enqueueWork.
public static void enqueueWork(#NonNull Context context, #NonNull Intent intent) {
enqueueWork(context, MyJobIntentService.class, JOB_ID, intent);
}
Also I've custom implementation of the FirebaseMessagingService. When I receive the push notification from FCM, I call the enqueueWork of my JobIntentService.
MyJobIntentService.enqueueWork(context, new Intent());
But method OnHandleWork not called on Android 8.0 and higher.
My manifest.xml.
<service android:name="com.company.MyJobIntentService"
android:permission="android.permission.BIND_JOB_SERVICE" />
Do you have any ideas why it work not correctly? Thank you.
Nothing incorrectly. Unfortunately, JobIntentService will not run immediately on Android 8.0 and higher.
When running as a pre-O service, the act of enqueueing work will generally start the service immediately, regardless of whether the device is dozing or in other conditions. When running as a Job, it will be subject to standard JobScheduler policies for a Job with a setOverrideDeadline(long) of 0: the job will not run while the device is dozing, it may get delayed more than a service if the device is under strong memory pressure with lots of demand to run jobs.
When testing,I new a empty project, it runs immediately when call, but when i use in a real complex project,it runs several minutes later after called.
I've spent some time experimenting with and studying the OSGi enRoute site. The Quick Start, and Base tutorials were really good. Now as a learning exercise, I'm creating my own example following the principles in those tutorials.
I've decided to reproduce the StageService from the blog post "Making JavaFX better with OSGi". Rather than using the org.apache.felix.dm and org.apache.felix.dm.annotation.api packages I want to use the OSGi standard SCR packages (org.osgi.service.component.*) along with the enRoute provider template.
So far everything has worked out nicely. But I'm stuck on one point. In the "Making JavaFX better with OSGi" tutorial the service is programmatically registered into the service registry using the org.apache.felix.dm.DependencyManager like this:
#Override
public void start(Stage primaryStage) throws Exception {
BundleContext bc = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
DependencyManager dm = new DependencyManager(bc);
dm.add(dm.createComponent()
.setInterface(StageService.class.getName(), null)
.setImplementation(new StageServiceImpl(primaryStage)));
}
My assumption is that in this example the DependencyManager is an Apache Felix specific feature rather than an OSGi standard. I would like to have my enRoute provider depend only on OSGi standard features.
So my question is simply:
How would one register a service in the service registry programmatically using only OSGi standard features? (I know from following the enRoute tutorials that if my component implements the exported service that SCR will automatically register my component in the service registry when my component is activated. The problem with this solution though is that when my component is activated it has to launch the JavaFX application in a different thread so as to not block the thread in use by the SCR until the JavaFX application terminates. Because of this, my component must programmatically register the service in the service registry. Otherwise it won't be guaranteed to be available upon registration.)
For reference, here is what I currently have:
private void registerService(Stage stage) {
DependencyManager dm = new DependencyManager(bundle().getBundleContext());
dm.add(
dm.createComponent()
.setInterface(StageService.class.getName(), null)
.setImplementation(new StageServiceImpl(primaryStage))
);
}
But instead I want to replace it with this:
private void registerService(Stage stage) {
// How to register service in service registry using only OSGi standard features? (not the apache felix dependency manager)
}
UPDATE 1
Following BJ Hargrave's recommendation I tried to register the service directly from the bundle context as follows:
FrameworkUtil
.getBundle(getClass())
.getBundleContext()
.registerService(StageService.class, new StageServiceImpl(primaryStage), null);
After doing this and trying to resolve the enRoute application project the following error occurs:
org.osgi.service.resolver.ResolutionException: Unable to resolve
<> version=null: missing requirement
com.github.axiopisty.osgi.javafx.launcher.application
-> Unable to resolve com.github.axiopisty.osgi.javafx.launcher.application
version=1.0.0.201608172037: missing requirement
objectClass=com.github.axiopisty.osgi.javafx.launcher.api.StageService]
I have uploaded the project to github so you can reproduce the error.
Update 2
The build tab in the bnd.bnd file in the provider module shows the following warning:
The servicefactory:=true directive is set but no service is provided, ignoring it
Might this have something to do with the application module not being able to be resolved?
In rare cases it is necessary to register a 'service by hand' using the standard OSGi API. Try very hard to avoid this case because if you start to register (and maybe depend) on services that you manually register you get a lot of responsibility that is normally hidden from view. For example, you have to ensure that the services you register are also unregistered.
One of the rare cases where this is necessary is when you have to wait for a condition before you can register your service. For example, you need to poll a piece of hardware before you register a service for the device. You will need to control the CPU but at that moment you cannot yet register a service. In that case you create an immediate component and register the service manually.
To register a service manually you require a BundleContext object. You can get that objectvia the activate method, just declare a Bundle Context in its arguments and it is automatically injected:
#Activate
void activate( BundleContext context) {
this.context = context;
}
You can now register a service with the bundle context:
void register(MyService service) {
Hashtable<String,Object> properties = new Hashtable<>();
properties.put("foo", "bar");
this.registration = context.registerService( MyService.class, service, properties );
}
However, you now have the responsibility to unregister this service in your deactivate. If you do not clean up this service then your component might be deactivated while your service still floats around. Your service is unmanaged. (Although when the bundle is stopped it will be cleaned up.)
#Deactivate
void deactivate() {
if ( this.registration != null)
this.registration.unregister();
}
If you create the service is a call back or background thread then you obviously have to handle the concurrency issues. You must ensure that there is no race condition that you register a service while the deactivate method has finished.
This text has also been added to the DS Page of OSGi enRoute
Reading the OSGi spec would help you understand the service API.
But this should do it:
ServiceRegistration<StageService> reg = bc.registerService(StageService.class, new StageServiceImpl(primaryStage), null);
We are using Java GRPC for one of our internal services and we have a server side interceptor that we use to grab information from the headers and set them up in a logging context that that uses a ThreadLocal internally.
So in our interceptor we do something similar to this:
LogMessageBuilder.setServiceName("some-service");
final String someHeaderWeWant = headers.get(HEADER_KEY);
final LoggerContext.Builder loggingContextBuilder = new LoggerContext.Builder()
.someFieldFromHeaders(someHeaderWeWant);
LoggerContext.setContext(loggingContextBuilder.build());
Then in our service call we access it like this:
LoggingContext loggingContext = LoggingContext.getCurrent()
However the current context is null some of the time.
We then tried to use the GRPC Context class like below:
LogMessageBuilder.setServiceName("some-service");
final String someHeaderWeWant = headers.get(HEADER_KEY);
final LoggerContext.Builder loggingContextBuilder = new LoggerContext.Builder()
.someFieldFromHeaders(someHeaderWeWant);
Context.current().withValue(LOGGING_CONTEXT_KEY, loggingContextBuilder.build()).attach()
Then accessing it in the service call like:
LoggingContext context = LOGGING_CONTEXT_KEY.get(Context.current())
However that is also sometimes null and if I print out the memory addresses it appears that early on the context is always the ROOT context regardless of me attaching in the interceptor, but after a few calls the contexts are correct and the logger data is there like it should.
So if anyone has any ideas or better ways to propagate data from an interceptor to the service call I would love to hear it.
Each callback can be called on a different thread, so the thread-local has to be set for each callback. It seems you may accidentally be getting Contexts intended for other RPCs.
grpc-java 0.12.0 should be released this week. Context has been partially integrated in 0.12.0, and we also added Contexts.interceptCall() which is exactly what you need: it attaches and detaches the context for each callback.
In 0.12.0, you should now see new contexts being created for each server call (instead of ROOT) and contexts propagated from client calls to StreamObserver callbacks.
As another note, unlike ThreadLocal Context is intended to be tightly scoped: after attach(), you should generally have a try-finally to detach().
I'm working on an Android app that needs to maintain a network connection to a chat server. I understand that I can create a service to initiate the connection to the server, but how would the service notify an Android Activity of new incoming messages? The Activity would need to update the view to show the new messages. I'm pretty new to Android, so any help is appreciated. Thanks!
Can you pass a handler to your service?
First, define your handler as an interface. This is an example, so yours may be more complex.
public interface ServerResponseHandler {
public void success(Message[] msgs); // msgs may be null if no new messages
public void error();
}
Define an instance of your handler in your activity. Since it's an interface you'll provide the implementation here in the activity, so you can reference the enclosing activity's fields and methods from within the handler.
public class YourActivity extends Activity {
// ... class implementation here ...
updateUI() {
// TODO: UI update work here
}
ServerResponseHandler callback = new ServerResponseHandler() {
#Override
public void success(Message[] msgs) {
// TODO: update UI with messages from msgs[]
YourActivity.this.updateUI();
}
#Override
public void error() {
// TODO: show error dialog here? (or handle error differently)
}
}
void onCheckForMessages() {
networkService.checkForMessages(callback);
}
and NetworkService would contain something like:
void checkForMessages(ServerResponseHandler callback) {
// TODO: contact server, check for new messages here
// call back to UI
if (successful) {
callback.success(msgs);
} else {
callback.error();
}
}
Also, as Aleadam says, you should also be away that a service runs on the same thread by default. This is often not preferred behavior for something like networking. The Android Fundamentals Page on Services explicitly warns against networking without separate threads:
Caution: A service runs in the main thread of its hosting process—the service does not
create its own thread and does not run in a separate process (unless you specify
otherwise). This means that, if your service is going to do any CPU intensive work or
blocking operations (such as MP3 playback or networking), you should create a new thread
within the service to do that work. By using a separate thread, you will reduce the
risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
For more information on using threads in your service, check out the SO articles Application threads vs Service threads and How to start service in new thread in android
Did you check the Service API page: http://developer.android.com/reference/android/app/Service.html ?
It has a couple of examples on how to interact with a Service.
The service runs on the same thread and the same Context as the Activity. Check also here: http://developer.android.com/reference/android/content/Context.html#bindService%28android.content.Intent,%20android.content.ServiceConnection,%20int%29
Finally, take a look also at Lars Vogel's article: http://www.vogella.de/articles/AndroidServices/article.html
One common and useful approach is to register a broadcast receiver in your Activity, and have the Service send out notification events when it has useful data. I find this to be easier to manage than implementing a handler via a callback, mainly because it makes it easier and safer when there is a configuration change. If you pass a direct Activity-reference to the Service then you have to be very careful to clear it when the Activity is destroyed (during rotation, or backgrounding), otherwise you get a leak.
With a Broadcast Receiver you still have to unregister when the Activity is being destroyed, however the Service never has a direct reference to the Activity so if you forget the Activity will not be leaked. It is also easier to have the Activity register to listen to a topic when it is created, since it never has to obtain a direct reference to the Service...
Lars Vogel's article discusses this approach, it is definitely worth reading! http://www.vogella.com/tutorials/AndroidServices/article.html#using-receiver
I want to build a REST Client on an android phone.
The REST server exposes several resources, e.g. (GET)
http://foo.bar/customer List of all customer
http://foo.bar/customer/4711 The customer with id 4711
http://foo.bar/customer/vip List of all VIP customer
http://foo.bar/company List of all companys
http://foo.bar/company/4711 The company with the ID 4711
http://foo.bar/company/vip List of all VIP companys
I (think) I know how to talk to the REST server and get the information I need. I would implement a REST Client class with an API like this
public List<Customer> getCustomers();
public Customer getCustomer(final String id);
public List<Customer> getVipCustomer();
public List<Company> getCompanies();
public Customer getCompany(final String id);
public List<Customer> getVipCompanies();
Referred to the presentation "Developing Android REST client applications" from Virgil Dobjanschi I learned that it is no good idea to handle the REST request in an Worker Thread of the Activity. Instead I should use the Service API.
I like the idea of having a Singleton ServiceHelper which binds to a (Local) Service but I am afraid that I did not understand the Service concept correct.
For now I do not understand how to report a REST call result (done asynchrounous in a Service) back to the caller Activity. I also wonder if I need ONE Service which handles all REST requests (with different return types) or if I need a dedicated service for each REST request.
Probably I have many other understanding problems so the best thing for me would be a sample application which meets my needs. My use case is not unusual and I hope there is in example application out there.
Would you please let me know!
Any other suggestions which points me in the correct implementation direction are also helpful (Android API-Demo does not match my use case).
Thanks in advance.
Klaus
EDIT: Similar Topics found on SO (after posting this) which lead me in the direction I need (minimizing the complex "Dobjanschi pattern"):
Android: restful API service
OverView
Edit:
Anyone interest also consider taking a look at RESTful android this might give you a better look about it.
What i learned from the experience on trying to implement the Dobjanschi Model, is that not everything is written in stone and he only give you the overview of what to do this might changed from app to app but the formula is:
Follow this ideas + Add your own = Happy Android application
The model on some apps may vary from requirement some might not need the Account for the SyncAdapter other might use C2DM, this one that i worked recently might help someone:
Create an application that have Account and AccountManager
It will allow you to use the SyncAdapter to synchronized your data. This have been discussed on Create your own SyncAdapter
Create a ContentProvider (if it suits your needs)
This abstraction allows you to not only access the database but goes to the ServiceHelper to execute REST calls as it has one-per-one Mapping method with the REST Arch.
Content Provider | REST Method
query ----------------> GET
insert ----------------> PUT
update ----------------> POST
delete ----------------> DELETE
ServiceHelper Layering
This guy will basicly start (a) service(s) that execute a Http(not necessarily the protocol but it's the most common) REST method with the parameters that you passed from the ContentProvider. I passed the match integer that is gotten from the UriMatcher on the content Provider so i know what REST resource to access, i.e.
class ServiceHelper{
public static void execute(Context context,int match,String parameters){
//find the service resource (/path/to/remote/service with the match
//start service with parameters
}
}
The service
Gets executed (I use IntentService most of the time) and it goes to the RESTMethod with the params passed from the helper, what is it good for? well remember Service are good to run things in background.
Also implement a BroadCastReceiver so when the service is done with its work notify my Activity that registered this Broadcast and requery again. I believe this last step is not on Virgill Conference but I'm pretty sure is a good way to go.
RESTMethod class
Takes the parameters, the WS resource(http://myservice.com/service/path) adds the parameters,prepared everything, execute the call, and save the response.
If the authtoken is needed you can requested from the AccountManager
If the calling of the service failed because authentication, you can invalidate the authtoken and reauth to get a new token.
Finally the RESTMethod gives me either a XML or JSON no matter i create a processor based on the matcher and pass the response.
The processor
It's in charged of parsing the response and insert it locally.
A Sample Application? Of course!
Also if you are interesting on a test application you look at Eli-G, it might not be the best example but it follow the Service REST approach, it is built with ServiceHelper, Processor, ContentProvider, Loader, and Broadcast.
Programming Android has a complete chapter (13. Exploring Content Providers) dedicated to 'Option B: Use the ContentProvider API' from Virgil's Google I/O talk.
We are not the only ones who see the benefits of this approach. At the Google I/O conference in May 2010, Virgil Dobjanschi of Google presented a talk that outlined the following three patterns for using content providers to integrate RESTful web services into Android applications...
In this chapter, we’ll explore the second pattern in detail with our second Finch video example; this strategy will yield a number of important benefits for your applications. Due to the elegance with which this approach integrates network operations into Android MVC, we’ve given it the moniker “Network MVC.”
A future edition of Programming Android may address the other two approaches, as well as document more details of this Google presentation. After you finish reading this chapter, we suggest that you view Google’s talk.
Highly recommended.
Programming Android by Zigurd Mednieks, Laird Dornin, G. Blake Meike, and Masumi Nakamura. Copyright 2011 O’Reilly Media, Inc., 978-1-449-38969-7.
"Developing Android REST client applications" by Virgil Dobjanschi led to much discussion, since no source code was presented during the session or was provided afterwards.
A reference implementation is available under http://datadroid.foxykeep.com (the Google IO session is mentioned under /presentation). It is a library which you can use in your own application.
Android Priority Job Queue was inspired by Dobjanschi's talk and sounds very promising to me.
Please comment if you know more implementations.
We have developped a library that adresses this issue : RoboSpice.
The library uses the "service approach" described by Virgil Dobjanschi and Neil Goodmann, but we offer a complete all-in-one solution that :
executes asynchronously (in a background AndroidService) network
requests that will return POJOs (ex: REST requests)
caches results (in Json, or Xml, or flat text files, or binary files)
notifies your activities (or any other context) of the result of the network
request if they are still alive
doesn't notify your activities of the
result if they are not alive anymore
notifies your activities on
their UI Thread
uses a simple but robust exception handling model
supports multiple ContentServices to aggregate different web services
results
supports multi-threading of request executions
is strongly
typed !
is open source ;)
and tested
We are actually looking for feedback from the community.
Retrofit could be very helpful here, it builds an Adapter for you from a very simple configuration like:
Retrofit turns your REST API into a Java interface.
public interface GitHubService {
#GET("/users/{user}/repos")
List<Repo> listRepos(#Path("user") String user);
}
The RestAdapter class generates an implementation of the GitHubService interface.
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
Each call on the generated GitHubService makes an HTTP request to the remote webserver.
List<Repo> repos = service.listRepos("octocat");
for more information visit the official site: http://square.github.io/retrofit/
Note: the adapter RestAdapter you get from Retrofit is not derived from BaseAdapter you should make a wrapper for it somehow like this SO question
Why is my ListView empty after calling setListAdapter inside ListFragment?
This is a little late but here is an article which explains the first pattern from the talk:
http://www.codeproject.com/Articles/429997/Sample-Implementation-of-Virgil-Dobjanschis-Rest-p
The thing I like about the first pattern is that the interface to the rest methods is a plain class, and the Content Provider is left to simply provide access to the database.
You should check out the source code for Google's official I/O 2010 app, for starters, particularly the SyncService and the various classes in the io subpackage.
Good news guys.
An implementation of the service helper is available here: https://github.com/MathiasSeguy-Android2EE/MythicServiceHelper
It's an open source project (Apache 2).
I am at the beginning of the project. I've done a project where I defined the pattern to do, but i haven't yet extract the code to make a clean librairy.
It will be done soon.