I made this post because I don't understand how transaction works using GreenDao and I would love to get some explanation/recent tutorial.
Despite of reading the Greendao github, I don't understand how the main activity works. For example:
...
Note note = new Note(null, noteText, comment, new Date(), NoteType.TEXT);
noteDao.insert(note)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Note>() {
#Override
public void call(Note note) {
Log.d("DaoExample", "Inserted new note, ID: " + note.getId());
updateNotes();
}
});
...
Do the observeOn method sends every insertion/update to one limited buffer? so, it will manage automatically the insertion to the real database when every operation was finished whithout problems?
Reading its API, we could see that they use rxTx and rxTxPlain for transactions (other way?), and finding out where are performed, I have to say I misunderstood everything. For example:
...
public void testConcurrentInsertDuringTx() throws InterruptedException {
...
Runnable runnable2 = new Runnable() {
#Override
public void run() {
dao.insertInTx(createEntity(null));
}
};
Runnable runnable3 = new Runnable() {
#Override
public void run() {
daoSession.runInTx(new Runnable() {
#Override
public void run() {
dao.insert(createEntity(null));
}
});
}
};
...
// Builds the statement so it is ready immediately in the thread
dao.insert(createEntity(null));
doTx(new Runnable() {
#Override
public void run() {
dao.insert(createEntity(null));
}
});
latchThreadsDone.await();
assertEquals(7, dao.count());
}
...
I know this is an example, but I don't know the diferences of using the rx methods and the observeOn/subscribe ones
protected void doTx(final Runnable runnableInsideTx) {
daoSession.runInTx(new Runnable() {
#Override
public void run() {
latchInsideTx.countDown();
// Give the concurrent thread time so it will try to acquire locks
try {
Thread.sleep(TIME_TO_WAIT_FOR_THREAD);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
runnableInsideTx.run();
}
});
}
I read some topics about transactions, but they are obsoletes or maybe, I didn't understand them correctly:
SQLite transaction behaviour using greendao
Android - Green Dao Multiple Transaction
Transactions in GreenDao
greenDAO 40 seconds to insert 600 records
https://groups.google.com/forum/#!topic/greendao/PXRwCRTbP6c
Someone could help me giving me some explanation/recent tutorial? Greendao have these methods as experimentals. Thanks in advance
I'm essentially trying to create a SystemService in Android. I read that intercommunication from an app to this service should be handled by a Handler?
So what about returning some object from the Service's function to the calling app? How can this be handled.
To make my question more clear, Imagine I have a Service TestService with the following method definitions:
public class TestService extends ITestService.Stub {
public TestService(Context context) {
super();
mContext = context;
mWorker = new TestWorkerThread("TestServiceWorker");
mWorker.start();
Log.i(TAG, "Spawned worker thread");
}
public void setValue(int val) {
Message msg = Message.obtain();
msg.what = TestWorkerHandler.MESSAGE_SET;
msg.arg1 = val;
mHandler.sendMessage(msg);
}
public Object getValue() {
// ********************* QUESTION HERE *****************
// Can I call this method directly??
// Or do I have to process this through the handler?????
}
private class TestWorkerThread extends Thread {
public TestWorkerThread(String name) {
super(name);
}
public void run() {
Looper.prepare();
mHandler = new TestWorkerHandler();
Looper.loop();
}
}
private class TestWorkerHandler extends Handler {
private static final int MESSAGE_SET = 0;
#Override
public void handleMessage(Message msg) {
try {
if (msg.what == MESSAGE_SET) {
Log.i(TAG, "set message received: " + msg.arg1);
}
} catch (Exception e) {
// Log, don't crash!
Log.e(TAG, "Exception in TestWorkerHandler.handleMessage:", e);
}
}
}
}
This is what I understand from the above in order to be synchronous we generally make the setValue to be executed as part of the handleMessage()
What about the getValue method can make a call to this method using the Service instance and process it normally like how we do traditionally? Or do I have to work with the handler which is highly unlikely (I beleive). Kindly let me know the best process to deal with in this scenario.
Thanks
You don't HAVE to use a Handler to do any of that. If you've created an AIDL file that describes the communication with the service then you're done: all you have to do next is implement the AIDL methods inside your service.
When AIDL is translated into java code by the Android "compiler", you functions will all be blocking (the client will wait for the service to finish the methods).
If you specifically add the keyword 'oneway' then the method call won't be blocking.
You should check out Google's documentation on IBinder to understand things a little better.
I do not use ksoap2
The callings must be asynchronously because other way honeycomb does not accept and it throws this exception http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
I am deriving the codes from .NET and Android has a very different architecturing than .NET. because of this when you leave comment please take notice of this fact.
In code block I will call different webmethods at least 5 or 6 times.
the code structure goes like this
public void X(){
int a = webMethodA();
. doSomethingWith a
.
.
b = webMethodB(a);
.
. doSomethingWith b
.
.
c = webMethod(b);
.
.
.
}
I tried to make it using with asyncTask and Handler, I could take result value but the problem is I could not handle the result value on X method. I have to use return values in X method block
For .net datasets it is better to store your data in your self designed Object collections that can be same in Webservice and android.
for example define class Person in webservice and Android which are same and deliver it.
you can use json in .Net and Android to serialize and deserialize your objects to a json string instead of using .Net xml.
for threading is this code your answer?
protected void btnCallWebservice_onClick() {
final Runnable r = new Runnable()
{
public void run()
{
threadWebservice();
}
};
performOnBackgroundThread(r);
}
public Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
private void threadWebservice() {
try {
// call your webservice here
} catch (final Exception e) {
}
}
I have created IntentService with infinite loop inside the onHandleIntent then add static methods start,resume,pause,stop to directly call it within my Activities.
The scenario is, inside the infinite loop, I am calling callback methods which is creating a new thread to execute long process.
The problem is, I am worrying about continuously creating Threads due to infinite loop. I am pretty sure that there is better way to manage it. I am thinking of ThreadPool or something enable to use only one thread in a sequential manner. So that, I am saving time,memory,overheads etc..
OTHER APPROACH ARE VERY WELCOME. Ask me other information as needed. Then, I will update here.
Here are my codes(take a look at SampleCallback):
IntentService
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SampleCallbackIntentService extends IntentService {
private final String LOG_LOGCAT_TAG = "SampleCallbackIntentService";
private Handler _handler;
public SampleCallbackIntentService(String name) {
super(name);
}
#Override
public void onCreate() {
super.onCreate();
// initialize variables for pause & resume thread
_mPauseLock = new Object();
_mPaused = false;
_mFinished = false;
// initialize handler to switch to UI/Main thread
_handler = new Handler()
{
#Override
public void handleMessage(final Message msg)
{
_callback.doSomethingFromUIThread(msg);
}
};
}
private final SampleCallback _callback = new SampleCallback() {
#Override
public void doSomethingFromCurrentThread(final Object object) {
new Thread(new Runnable() {
#Override
public void run() {
//do long running process.
// I will access object here.
}
}).start();
}
#Override
public void doSomethingFromUIThread(final Message msg) {
//may update UI here.
}
};
private final int CALLBACK_MESSAGE = 1;
#Override
protected void onHandleIntent(Intent arg0) {
Log.i(LOG_LOGCAT_TAG, "loop started");
while (!_mFinished) {
// do stuff here
// create the object variable. Then pass to callback method
_callback.doSomethingFromCurrentThread(object);
// process and create the result to pass
String someResult = "some result here";
_handler.sendMessage(_handler.obtainMessage(CALLBACK_MESSAGE, someResult));
synchronized (_mPauseLock) {
while (_mPaused) {
try {
Log.i(LOG_LOGCAT_TAG, "loop paused");
_mPauseLock.wait();
Log.i(LOG_LOGCAT_TAG, "loop resumed");
} catch (InterruptedException e) {
Log.e(LOG_LOGCAT_TAG, "error occured on pause", e);
}
}
}
try {
//using sleep here might be not good design.
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(LOG_LOGCAT_TAG, "error occured on sleep", e);
}
}
Log.i(LOG_LOGCAT_TAG, "loop ended");
}
private static Object _mPauseLock;
private static boolean _mPaused;
private static boolean _mFinished;
public static void start(Context context) {
Intent service = new Intent(context, SampleCallbackIntentService .class);
if(context.startService(service)==null) {
Log.e(LOG_LOGCAT_TAG, "Service cannot be started");
} else {
Log.i(LOG_LOGCAT_TAG, "start() called");
}
}
/**
* Call this on pause.
*/
public static void pause() {
Log.i(LOG_LOGCAT_TAG, "pause() called");
synchronized (_mPauseLock) {
_mPaused = true;
}
}
/**
* Call this on resume.
*/
public static void resume() {
Log.i(LOG_LOGCAT_TAG, "resume() called");
synchronized (_mPauseLock) {
_mPaused = false;
_mPauseLock.notifyAll();
}
}
public static void stop() {
if(_mPauseLock == null) return;
synchronized (_mPauseLock) {
Log.i(LOG_LOGCAT_TAG, "stop() called");
_mFinished = true;
}
}
}
SampleCallback
import android.os.Message;
public interface SampleCallback {
public void doSomethingFromCurrentThread(final Object object);
public void doSomethingFromUIThread(final Message msg);
}
UPDATES1
I am using location api aside from google api. I will create a android library project and use that api to get the latest location (e.g. every 2secs) in the background.
On the application side, just need to call static methods to use it (e.g. start(context, callback), pause(), resume(), stop()). It has callbacks to obtain the location. After obtaining the needed information from the location object, I will create a new thread to call my own created callbacks (which implemented by the application side).
You can use AsyncTask instead of creating a new thread every time? AsyncTask manages a fixed pool of threads (or one background thread - depending on Android version) and allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
However I wonder why do you need to create an infinite loop inside the onHandleIntent method? By doing that you prevent your IntentService from receiving further Intents. Since in IntentService:
All requests are handled on a single worker thread -- they may take as
long as necessary (and will not block the application's main loop),
but only one request will be processed at a time.
I think you want to execute some long-running code out of the UI thread in the IntentService. But that doesn't require the creation of an infinite loop in the IntentService worker thread. Just send the requests as needed to the IntentService using Context.startService(Intent) call. If you want IntentService to send back some result or just call a callback in the UI thread you can pass a Messenger (or a ResultReceiver) object with the Intent.
Activity:
final Handler uiHandler = new Handler(Looper.getMainLooper());
private void postTask() {
Intent intent = new Intent("com.yourservice.DOACTION");
intent.putExtra("messenger", new Messenger(handler));
intent.putExtra("object", YourObject()); // pass other Parcelable objects
startService(intent);
}
IntentService:
protected void onHandleIntent(Intent intent) {
Messenger messenger = intent.getParcelableExtra("messenger");
YourObject object = intent.getParcelableExtra("object");
//... do work here ...
Message msg = Message.obtain();
msg.what = CALLBACK_MESSAGE;
msg.setData(someResult);
messenger.send(Message.obtain());
}
Look into the docs for ExecutorService (not to be confused with Android Services) and the Executors package. There are a few examples there on how to use thread pools.
So wait, why do you need to use all these callbacks? Can't you just have each intent encode what needs to be done and then have your onHandleIntent execute different code based on the information of the intent. This is the way IntentService is intended to be used.
You shouldn't be doing any of the thread handling in the IntentSerivce. The IntentService is supposed to be handling all the threading code (and you should let it because it's probably highly optimized).
I'm looking to make a service which I can use to make calls to a web-based REST API.
Basically I want to start a service on app init then I want to be able to ask that service to request a url and return the results. In the meantime I want to be able to display a progress window or something similar.
I've created a service currently which uses IDL, I've read somewhere that you only really need this for cross app communication, so think these needs stripping out but unsure how to do callbacks without it. Also when I hit the post(Config.getURL("login"), values) the app seems to pause for a while (seems weird - thought the idea behind a service was that it runs on a different thread!)
Currently I have a service with post and get http methods inside, a couple of AIDL files (for two way communication), a ServiceManager which deals with starting, stopping, binding etc to the service and I'm dynamically creating a Handler with specific code for the callbacks as needed.
I don't want anyone to give me a complete code base to work on, but some pointers would be greatly appreciated.
Code in (mostly) full:
public class RestfulAPIService extends Service {
final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
public IBinder onBind(Intent intent) {
return binder;
}
public void onCreate() {
super.onCreate();
}
public void onDestroy() {
super.onDestroy();
mCallbacks.kill();
}
private final IRestfulService.Stub binder = new IRestfulService.Stub() {
public void doLogin(String username, String password) {
Message msg = new Message();
Bundle data = new Bundle();
HashMap<String, String> values = new HashMap<String, String>();
values.put("username", username);
values.put("password", password);
String result = post(Config.getURL("login"), values);
data.putString("response", result);
msg.setData(data);
msg.what = Config.ACTION_LOGIN;
mHandler.sendMessage(msg);
}
public void registerCallback(IRemoteServiceCallback cb) {
if (cb != null)
mCallbacks.register(cb);
}
};
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
// Broadcast to all clients the new value.
final int N = mCallbacks.beginBroadcast();
for (int i = 0; i < N; i++) {
try {
switch (msg.what) {
case Config.ACTION_LOGIN:
mCallbacks.getBroadcastItem(i).userLogIn( msg.getData().getString("response"));
break;
default:
super.handleMessage(msg);
return;
}
} catch (RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
public String post(String url, HashMap<String, String> namePairs) {...}
public String get(String url) {...}
};
A couple of AIDL files:
package com.something.android
oneway interface IRemoteServiceCallback {
void userLogIn(String result);
}
and
package com.something.android
import com.something.android.IRemoteServiceCallback;
interface IRestfulService {
void doLogin(in String username, in String password);
void registerCallback(IRemoteServiceCallback cb);
}
and the service manager:
public class ServiceManager {
final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();
public IRestfulService restfulService;
private RestfulServiceConnection conn;
private boolean started = false;
private Context context;
public ServiceManager(Context context) {
this.context = context;
}
public void startService() {
if (started) {
Toast.makeText(context, "Service already started", Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
context.startService(i);
started = true;
}
}
public void stopService() {
if (!started) {
Toast.makeText(context, "Service not yet started", Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
context.stopService(i);
started = false;
}
}
public void bindService() {
if (conn == null) {
conn = new RestfulServiceConnection();
Intent i = new Intent();
i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
context.bindService(i, conn, Context.BIND_AUTO_CREATE);
} else {
Toast.makeText(context, "Cannot bind - service already bound", Toast.LENGTH_SHORT).show();
}
}
protected void destroy() {
releaseService();
}
private void releaseService() {
if (conn != null) {
context.unbindService(conn);
conn = null;
Log.d(LOG_TAG, "unbindService()");
} else {
Toast.makeText(context, "Cannot unbind - service not bound", Toast.LENGTH_SHORT).show();
}
}
class RestfulServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className, IBinder boundService) {
restfulService = IRestfulService.Stub.asInterface((IBinder) boundService);
try {
restfulService.registerCallback(mCallback);
} catch (RemoteException e) {}
}
public void onServiceDisconnected(ComponentName className) {
restfulService = null;
}
};
private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
public void userLogIn(String result) throws RemoteException {
mHandler.sendMessage(mHandler.obtainMessage(Config.ACTION_LOGIN, result));
}
};
private Handler mHandler;
public void setHandler(Handler handler) {
mHandler = handler;
}
}
Service init and bind:
// this I'm calling on app onCreate
servicemanager = new ServiceManager(this);
servicemanager.startService();
servicemanager.bindService();
application = (ApplicationState)this.getApplication();
application.setServiceManager(servicemanager);
service function call:
// this lot i'm calling as required - in this example for login
progressDialog = new ProgressDialog(Login.this);
progressDialog.setMessage("Logging you in...");
progressDialog.show();
application = (ApplicationState) getApplication();
servicemanager = application.getServiceManager();
servicemanager.setHandler(mHandler);
try {
servicemanager.restfulService.doLogin(args[0], args[1]);
} catch (RemoteException e) {
e.printStackTrace();
}
...later in the same file...
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case Config.ACTION_LOGIN:
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
try {
...process login results...
}
} catch (JSONException e) {
Log.e("JSON", "There was an error parsing the JSON", e);
}
break;
default:
super.handleMessage(msg);
}
}
};
If your service is going to be part of you application then you are making it way more complex than it needs to be. Since you have a simple use case of getting some data from a RESTful Web Service, you should look into ResultReceiver and IntentService.
This Service + ResultReceiver pattern works by starting or binding to the service with startService() when you want to do some action. You can specify the operation to perform and pass in your ResultReceiver (the activity) through the extras in the Intent.
In the service you implement onHandleIntent to do the operation that is specified in the Intent. When the operation is completed you use the passed in ResultReceiver to send a message back to the Activity at which point onReceiveResult will be called.
So for example, you want to pull some data from your Web Service.
You create the intent and call startService.
The operation in the service starts and it sends the activity a message saying it started
The activity processes the message and shows a progress.
The service finishes the operation and sends some data back to your activity.
Your activity processes the data and puts in in a list view
The service sends you a message saying that it is done, and it kills itself.
The activity gets the finish message and hides the progress dialog.
I know you mentioned you didn't want a code base but the open source Google I/O 2010 app uses a service in this way I am describing.
Updated to add sample code:
The activity.
public class HomeActivity extends Activity implements MyResultReceiver.Receiver {
public MyResultReceiver mReceiver;
public void onCreate(Bundle savedInstanceState) {
mReceiver = new MyResultReceiver(new Handler());
mReceiver.setReceiver(this);
...
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, QueryService.class);
intent.putExtra("receiver", mReceiver);
intent.putExtra("command", "query");
startService(intent);
}
public void onPause() {
mReceiver.setReceiver(null); // clear receiver so no leaks.
}
public void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case RUNNING:
//show progress
break;
case FINISHED:
List results = resultData.getParcelableList("results");
// do something interesting
// hide progress
break;
case ERROR:
// handle the error;
break;
}
}
The Service:
public class QueryService extends IntentService {
protected void onHandleIntent(Intent intent) {
final ResultReceiver receiver = intent.getParcelableExtra("receiver");
String command = intent.getStringExtra("command");
Bundle b = new Bundle();
if(command.equals("query") {
receiver.send(STATUS_RUNNING, Bundle.EMPTY);
try {
// get some data or something
b.putParcelableArrayList("results", results);
receiver.send(STATUS_FINISHED, b)
} catch(Exception e) {
b.putString(Intent.EXTRA_TEXT, e.toString());
receiver.send(STATUS_ERROR, b);
}
}
}
}
ResultReceiver extension - edited about to implement MyResultReceiver.Receiver
public class MyResultReceiver implements ResultReceiver {
private Receiver mReceiver;
public MyResultReceiver(Handler handler) {
super(handler);
}
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
public interface Receiver {
public void onReceiveResult(int resultCode, Bundle resultData);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (mReceiver != null) {
mReceiver.onReceiveResult(resultCode, resultData);
}
}
}
Developing Android REST client applications has been an awesome resource for me. The speaker does not show any code, he just goes over design considerations and techniques in putting together a rock solid Rest Api in android. If your a podcast kinda person or not, I'd recommend giving this one at least one listen but, personally I've listened to it like 4 or five times thus far and I'm probably going to listen to it again.
Developing Android REST client applications
Author: Virgil Dobjanschi
Description:
This session will present architectural considerations for developing RESTful applications on the Android platform. It focuses on design patterns, platform integration and performance issues specific to the Android platform.
And there are so many considerations I really hadn't made in the first version of my api that I've had to refactor
Also when I hit
the post(Config.getURL("login"),
values) the app seems to pause for a
while (seems weird - thought the idea
behind a service was that it runs on a
different thread!)
No you have to create a thread yourself, a Local service runs in the UI thread by default.
I know #Martyn does not want full code, but I think this annotation its good for this question:
10 Open Source Android Apps which every Android developer must look into
Foursquared for Android is open-source, and have an interesting code pattern interacting with the foursquare REST API.
I would highly recommend the REST client Retrofit.
I have found this well written blog post extremely helpful, it also contains simple example code.
The author uses Retrofit to make the network calls and Otto to implement a data bus pattern:
http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html
Just wanted to point you all in the direction of an standalone class I rolled that incorporates all of the functionality.
http://github.com/StlTenny/RestService
It executes the request as non-blocking, and returns the results in an easy to implement handler. Even comes with an example implementation.
Lets say I want to start the service on an event - onItemClicked() of a button. The Receiver mechanism would not work in that case because :-
a) I passed the Receiver to the service (as in Intent extra) from onItemClicked()
b) Activity moves to the background. In onPause() I set the receiver reference within the ResultReceiver to null to avoid leaking the Activity.
c) Activity gets destroyed.
d) Activity gets created again. However at this point the Service will not be able to make a callback to the Activity as that receiver reference is lost.
The mechanism of a limited broadcast or a PendingIntent seems to be more usefull in such scenarios- refer to Notify activity from service
Note that the solution from Robby Pond is somehow lacking: in this way you only allow todo one api call at a time since the IntentService only handles one intent at a time. Often you want to perform parallel api calls. If you want todo this you have to extend Service instead of IntentService and create your own thread.
Also when I hit the post(Config.getURL("login"), values) the app seems to pause for a while (seems weird - thought the idea behind a service was that it runs on a different thread!)
In this case its better to use asynctask, which runs on a different thread and return result back to the ui thread on completion.
Robby provides a great answer, though I can see you still looking for more information. I implemented REST api calls the easy BUT wrong way. It wasn't until watching this Google I/O video that I understood where I went wrong. It's not as simple as putting together an AsyncTask with a HttpUrlConnection get/put call.
There is another approach here which basically helps you to forget about the whole management of the requests. It is based on an async queue method and a callable/callback based response.
The main advantage is that by using this method you'll be able to make the whole process (request, get and parse response, sabe to db) completely transparent for you. Once you get the response code the work is already done. After that you just need to make a call to your db and you are done.
It helps as well with the problematic of what happens when your activity is not active.
What will happen here is that you'll have all your data saved in your local database but the response won't be processed by your activity, that's the ideal way.