I have finally been dynamically update my UI using phonegap. I had to 
update couchbase-lite-java library REST API to implement the feed=continous 
and feed=longpoll parameters:

Here are the changes I made to the Router.java file to make it work:
    public Status do_GET_Document_active_tasks(Database _db, String _docID, 
String _attachmentName) {
        return do_GET_active_tasks(_db, _docID, _attachmentName);
    }
    
    private boolean longpollReplication = false;
    
    public Status do_GET_active_tasks(Database _db, String _docID, String 
_attachmentName) {
        // http://wiki.apache.org/couchdb/HttpGetActiveTasks
        String feed = getQuery("feed");
         
        longpollReplication = "longpoll".equals(feed);
        boolean continuous = !longpollReplication && "continuous".equals(
feed);
        
        String session_id = getQuery("session_id");
        
        ChangeListener listener = new ChangeListener() {
            
            ChangeListener self = this;
                
            @Override
            public void changed(ChangeEvent event) {
                
                Map<String,Object> activity = getActivity( event.getSource() 
);
                
                if (event.getTransition() != null ) {
                        
                    activity.put("transition_source", event.getTransition().
getSource());
                    activity.put("transition_destination", event.
getTransition().getDestination());
                    activity.put("trigger", event.getTransition().getTrigger
() );
                    Log.d(Log.TAG_ROUTER, "do_GET_active_tasks Transition [" 
+ event.getTransition().getTrigger() + "] Source:" + event.getTransition().
getSource() + ", Destination:" + event.getTransition().getDestination() );
                    
                }
                
                if(longpollReplication) {
                    Log.w(Log.TAG_ROUTER, "Router: Sending longpoll 
replication response");
                    sendResponse();
                    
                    if(callbackBlock != null) {
                        byte[] data = null;
                        try {
                            data = Manager.getObjectMapper().
writeValueAsBytes(activity);
                        } catch (Exception e) {
                            Log.w(Log.TAG_ROUTER, "Error serializing JSON", 
e);
                        }
                        OutputStream os = connection.getResponseOutputStream
();
                        try {
                            os.write(data);
                            os.close();
                        } catch (IOException e) {
                            Log.e(Log.TAG_ROUTER, "IOException writing to 
internal streams", e);
                        }
                    }
                    //remove this change listener because a new one will be 
added when this responds
                    event.getSource().removeChangeListener(self);
                } else {
                    Log.w(Log.TAG_ROUTER, "Router: Sending continous 
replication change chunk");
                    sendContinuousReplicationChanges(activity);
                }
                
                
                
            }
        };
        
        
        List<Map<String,Object>> activities = new ArrayList<Map<String,
Object>>();
        for (Database db : manager.allOpenDatabases()) {
            List<Replication> allReplicators = db.getAllReplications();
            if(allReplicators != null) {
                for (Replication replicator : allReplicators) {
                    
                    Map<String,Object> activity = getActivity( replicator );
                    
                    activities.add(activity);
                    
                    if (continuous || longpollReplication) {
                        
                        if (session_id != null) {
                            if (replicator.getSessionID().equals(session_id
)){
                                replicator.addChangeListener(listener);
                            }
                        } else {
                            replicator.addChangeListener(listener);
                        }
                    }
                }
            }
        }
       

        if (continuous || longpollReplication) {
            
            connection.setChunked(true);
            connection.setResponseCode(Status.OK);
            sendResponse();
            
            if (continuous && !activities.isEmpty()) {
                for (Map<String,Object> activity : activities) {
                    sendContinuousReplicationChanges(activity);
                }
            }
            
            // Don't close connection; more data to come
            return new Status(0);
        } else {
            connection.setResponseBody(new Body(activities));
            return new Status(Status.OK);
        }
    }
    
    private Map<String,Object> getActivity(Replication replicator) {
        
        Map<String,Object> activity = new HashMap<String,Object>();
        
        String source = replicator.getRemoteUrl().toExternalForm();
        String target = replicator.getLocalDatabase().getName();        
        
        if(!replicator.isPull()) {
            String tmp = source;
            source = target;
            target = tmp;
        }
        int processed = replicator.getCompletedChangesCount();
        int total = replicator.getChangesCount();
        String status = String.format("Processed %d / %d changes", processed
, total);
        if (! replicator.getStatus().name().equals( ReplicationStatus.
REPLICATION_ACTIVE.name() ) ) {
           status = replicator.getStatus().name();
        }
        int progress = (total > 0) ? Math.round(100 * processed / (float)
total) : 0;
       
        activity.put("type", "Replication");
        activity.put("task", replicator.getSessionID());
        activity.put("source", source);
        activity.put("target", target);
        
        if (replicator.getLastError() != null) {
            String msg = String.format("Replicator error: %s.  Repl: %s. 
 Source: %s, Target: %s",
                    replicator.getLastError(), replicator, source, target);
            Log.e(Log.TAG_ROUTER, msg);
            Throwable error = replicator.getLastError();
            int statusCode = 400;
            if (error instanceof HttpResponseException) {
                statusCode = ((HttpResponseException)error).getStatusCode();
            }
            Object[] errorObjects = new Object[]{ statusCode, replicator.
getLastError().toString() };
            activity.put("error", errorObjects);
            activity.put("status", Replication.ReplicationStatus.
REPLICATION_STOPPED);
            activity.put("progress", null);
            activity.put("change_count", null);
            activity.put("completed_change_count", null);
        } else {
            activity.put("status", status);
            activity.put("progress", progress);
            activity.put("change_count", total);
            activity.put("completed_change_count", processed);
        }

        return activity;
    }
    
    public void sendContinuousReplicationChanges(Map<String,Object> activity
) {
        try {
            String jsonString = Manager.getObjectMapper().writeValueAsString
(activity);
            if(callbackBlock != null) {
                byte[] json = (jsonString + "\n").getBytes();
                OutputStream os = connection.getResponseOutputStream();
                try {
                    os.write(json);
                    os.flush();
                } catch (Exception e) {
                    Log.e(Log.TAG_ROUTER, "IOException writing to internal 
streams", e);
                }
            }
        } catch (Exception e) {
            Log.w("Unable to serialize change to JSON", e);
        }
    }

If you would like to see how I implemented it in my phonegap app. you can 
check out my source code here.
https://github.com/deefactorial/openmoney-mobile/

I was not able to get feed=continuous to work in my phonegap app because it 
does not work for the changes API, But longpoll works quite nicely.

On Wednesday, 12 November 2014 14:46:28 UTC-8, Dominique Legault wrote:
>
> sorry string compare in java is different.
>
> String status = String.format("Processed %d / %d changes", processed, 
> total);
> if (! replicator.getStatus().name().equals( 
> ReplicationStatus.REPLICATION_ACTIVE 
> ) ) {
>    status = replicator.getStatus().name();
> } 
>
>
>
> On Wednesday, 12 November 2014 14:40:39 UTC-8, Dominique Legault wrote:
>>
>> What about adding:
>>
>> String status = String.format("Processed %d / %d changes", processed, 
>> total);
>> if (replicator.getStatus().name() != ReplicationStatus.REPLICATION_ACTIVE
>> ) {
>>     status = replicator.getStatus().name();
>> }
>>
>> to this line
>>
>> https://github.com/couchbase/couchbase-lite-java-core/blob/master/src/main/java/com/couchbase/lite/router/Router.java#L698
>>
>> At least I would be able to get the current status of the replication, 
>> and I could assume if it was Processed... that it was Active.
>>
>>
>> On Wednesday, 12 November 2014 12:10:06 UTC-8, Dominique Legault wrote:
>>>
>>> See my responses inline:
>>>
>>> On Tuesday, 11 November 2014 14:08:25 UTC-8, Traun Leyden wrote:
>>>>
>>>> See inline responses below:
>>>>
>>>>
>>>>> How can it go back to 2 / 2 changes once it has hit 2 / 3 changes ? 
>>>>>
>>>>>
>>>> That's definitely a bug.  Can you file a github issue here 
>>>> <https://github.com/couchbase/couchbase-lite-java-core> and mention: 
>>>>
>>>
>>>> * Is it a pull or push replication? 
>>>>
>>> * Which version of Couchbase Lite are you using?  (or a link to where 
>>>> you downloaded it and I can probably figure out from there)
>>>> * Is this sync'ing with a CouchDB database or a Sync Gateway?
>>>> * Is it possible to put the database or an equivalent database on a 
>>>> public URL so that we can test against it and try to reproduce the issue?
>>>>
>>>
>>> I'll try and reproduce the issue to see if it comes up. It may have been 
>>> that push replication surpassed the pull replication at that time, I'll get 
>>> the logs this time.
>>> Most recent version by doing this four days ago.
>>> phonegap plugin remove com.couchbase.lite.phonegap
>>> phonegap local plugin add https://
>>> github.com/couchbaselabs/Couchbase-Lite-PhoneGap-Plugin.git
>>> I am doing a sync to a sync_gateway
>>> The DB is on a public url, here is the source code:
>>> https://github.com/deefactorial/openmoney-mobile/ 
>>>
>>> Let me do some preliminary testing to see if I can reproduce the error 
>>> and I'll create a bug report with the logcat.
>>>
>>>
>>>  
>>>>
>>>>> The changes feed for documents only sends data when it changes, the 
>>>>> active_tasks is different in that it sends data continuously.
>>>>> When I turn off access to the internet the stream of continuous 
>>>>> responses stops.
>>>>>
>>>>
>>>> I'm not sure I understand this, can you describe it in more details?  
>>>> Are you saying that the HTTP response never finishes?
>>>>
>>>>  
>>>>
>>> When I get the active_tasks with feed=continuous I get a stream of 
>>> responses, often the data hasn't changed. It will be the same response 
>>> every time, until a document is changed in my local db, Why does it send 
>>> continuous responses when the response data has not changed.
>>> Here is an example log:
>>>
>>> 11-12 11:58:44.569: I/Web Console(3378): task{"progress":100,"target":"
>>> https://deefactorial%2B8%40gmail.com:123456@
>>> cloud.openmoney.cc:4984/openmoney_shadow/","source":"openmoney","type":"Replication","status":"Processed
>>>  
>>> 168 / 168 changes","task":"repl001"} at 
>>> file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.569: I/Web Console(3378): push sync connected handler 
>>> called at file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.620: I/Web Console(3378): 
>>> task{"progress":100,"target":"openmoney","source":"https://deefactorial
>>> %2B8%40gmail.com:[email protected]:4984/openmoney_shadow/","type":"Replication","status":"Processed
>>>  
>>> 6 / 6 changes","task":"repl002"} at 
>>> file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.620: I/Web Console(3378): pull sync connected handler 
>>> called at file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.846: I/Web Console(3378): task{"progress":100,"target":"
>>> https://deefactorial%2B8%40gmail.com:123456@
>>> cloud.openmoney.cc:4984/openmoney_shadow/","source":"openmoney","type":"Replication","status":"Processed
>>>  
>>> 168 / 168 changes","task":"repl001"} at 
>>> file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.846: I/Web Console(3378): push sync connected handler 
>>> called at file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.858: I/Web Console(3378): 
>>> task{"progress":100,"target":"openmoney","source":"https://deefactorial
>>> %2B8%40gmail.com:[email protected]:4984/openmoney_shadow/","type":"Replication","status":"Processed
>>>  
>>> 6 / 6 changes","task":"repl002"} at 
>>> file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:44.858: I/Web Console(3378): pull sync connected handler 
>>> called at file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:45.124: I/Web Console(3378): task{"progress":100,"target":"
>>> https://deefactorial%2B8%40gmail.com:123456@
>>> cloud.openmoney.cc:4984/openmoney_shadow/","source":"openmoney","type":"Replication","status":"Processed
>>>  
>>> 168 / 168 changes","task":"repl001"} at 
>>> file:///android_asset/www/js/index.js:5861
>>> 11-12 11:58:45.128: I/Web Console(3378): push sync connected handler 
>>> called at file:///android_asset/www/js/index.js:5861
>>>
>>> Notice how all those responses happened within 1 second, and there isn't 
>>> anything new in each of the responses.
>>>
>>> I have not seen any responses where the status has been anything but 
>>> "Processed [number] / [number] changes" in the Android version.
>>> When the replication stops (wifi connection disabled) the stream of 
>>> responses stops, there is no response that indicates it has stopped other 
>>> than the stream of responses has stopped.
>>>
>>>
>>>>> How do I detect the various different states that the replication is 
>>>>> in with the active_tasks API ?
>>>>> Idle when there isn't a change ?
>>>>> Active when changes are not equal ?
>>>>> and Stopped when the stream stops ?
>>>>>
>>>>> How do I know if a change has completed ?
>>>>> do I track the number of changes I have made and compare that to the 
>>>>> number of changes completed ?
>>>>>
>>>>> On Monday, 10 November 2014 11:12:03 UTC-8, Jens Alfke wrote:
>>>>>>
>>>>>>
>>>>>> > On Nov 10, 2014, at 10:56 AM, Dominique <[email protected]> 
>>>>>> wrote: 
>>>>>> > 
>>>>>> > What I would like to see is access to the Replication Change 
>>>>>> Listener through the REST API, similar to the Document Change Listener. 
>>>>>>
>>>>>> If you add "?feed=continuous" to _active_tasks it'll send push 
>>>>>> updates just like the _changes feed. 
>>>>>>
>>>>>> —Jens 
>>>>>>
>>>>>>  -- 
>>>>> You received this message because you are subscribed to the Google 
>>>>> Groups "Couchbase Mobile" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>>> an email to [email protected].
>>>>> To view this discussion on the web visit 
>>>>> https://groups.google.com/d/msgid/mobile-couchbase/24bf3b32-bb3a-4df4-ac5e-78481382345d%40googlegroups.com
>>>>>  
>>>>> <https://groups.google.com/d/msgid/mobile-couchbase/24bf3b32-bb3a-4df4-ac5e-78481382345d%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"Couchbase Mobile" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/mobile-couchbase/688b3a30-f3e8-47d0-911d-5fc4e2be27da%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to