I have a CouchDB database and I want to replicate it on an Android device using Cloudant
So what I am doing is:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
URI uri = null;
File path = getApplicationContext().getDir(DATASTORE_DIRECTORY, Context.MODE_PRIVATE);
try {
uri = new URI("http://XXX.XXX.XXX.X:XXXX/my_database/");
} catch (URISyntaxException e) {
Log.d("onCreate",e.getMessage());
}
DocumentStore ds = null;
try {
ds = DocumentStore.getInstance(path);
} catch (DocumentStoreNotOpenedException e) {
Log.d("onCreate",e.getMessage());
}
// Create a replicator that replicates changes from the remote
// database to the local DocumentStore.
Replicator replicator = ReplicatorBuilder.pull()
.from(uri)
.to(ds)
.addRequestInterceptors(new BasicAuthInterceptor("myUser:myPass"))
.build();
// Use a CountDownLatch to provide a lightweight way to wait for completion
CountDownLatch latch = new CountDownLatch(1);
Listener listener = new Listener(latch);
replicator.getEventBus().register(listener);
replicator.start();
try {
latch.await();
} catch (InterruptedException e) {
Log.d("onCreate",e.getMessage());
}
replicator.getEventBus().unregister(listener);
if (replicator.getState() != Replicator.State.COMPLETE) {
Log.d("onCreate","Error replicating FROM remote");// error
Log.d("onCreate",(listener.errors).toString());// error
} else {
Log.d("onCreate",(String.format("Replicated %d documents in %d batches",
listener.documentsReplicated, listener.batchesReplicated)));
}
}
I am getting two errors;
onCreate: Error replicating FROM remote onCreate:
onCreate:[java.lang.RuntimeException: Could not determine if the _bulk_get
endpoint is supported]
What I am doing wrong?
Related
first of all excuse my english, because i am not good in english. I'm looking for a way to retrieve information in android send from a nodeJS server with socket io. I have the impression that it is a problem of version. my code compiles very well, I do not manage to retrieve the information contained in a JS object.
here is the server code
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var data ={"msg": "hello i am the server"};
io.on('connection',function(socket){
console.log('one user connected '+socket.id);
socket.on('message',function(obj){
console.log(obj.text);
socket.emit('take', data);
})
socket.on('disconnect',function(){
console.log('one user disconnected '+socket.id);
})
})
http.listen(3000,function(){
console.log('server listening on port 3000');
})
the information I'm looking for is 'data'
here is the java code I use, I prefer to put the whole code in case the problem is elsewhere
public class MainActivity extends AppCompatActivity {
private Socket socket;
public String ReceiveMsg ="message par defaut ";
{
try {
socket = IO.socket("http://192.168.43.168:3000");
socket.connect();
} catch (URISyntaxException e) {
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = (EditText) findViewById(R.id.editText);
TextView textView = (TextView) findViewById(R.id.textView);
Button but = (Button) findViewById(R.id.button);
socket.connect();
String msg = takemsg(editText);
sendMsg(msg);
socket.on("take", handleIncomingMessages);
textView.setText(getAz(ReceiveMsg));
}
public String takemsg(EditText editText){
String msg = "message par defaut ";
msg = editText.getText().toString();
return msg;
}
public void sendMsg(String msg ){
JSONObject obj = new JSONObject();
try{
obj.put("text", msg);
socket.emit("message", obj);
}catch (JSONException e){
}
}
private Emitter.Listener handleIncomingMessages = new Emitter.Listener(){
#Override
public void call(final Object... args){
runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
try {
ReceiveMsg = data.getString("msg");
} catch (JSONException e) {
}
}
});
}
};
}
First I think we need more data.
What are the outputs of the server? Is connecting well?, check if your code in android is running.
If it's not connecting try setting the port with opts
...
try {
IO.Options opts = IO.Options();
opts.port = 3000;
socket = IO.socket("http://192.168.43.168", opts);
socket.connect();
} catch (URISyntaxException e) {
...
check if your service is alive. for services exists some returns that allows to maintain your service working.
https://developer.android.com/reference/android/app/Service.html#START_STICKY
we must put in the manifest
<uses-permission android:name="android.permission.INTERNET" />
to allow the application to use the network
I downloaded my service account credential json file from Firebase console placed it earlier in the main directory of GAE endpoint project when I run my backed locally it gives Security exception.
java.security.AccessControlException: access denied ("java.io.FilePermission" "\src\main\secret.json" "read")
I tried placing the .json file under the src directory also but no help.
You should place the json file in src/main/resources
I found a couple ways to approach this. First is by getting it from a file over an internet stream. The other is locally.
INTERNET WAY
My first method involved storing the file on my public dropbox folder. I got the shareable link (make sure it ends in .json) and pasted it in the string example "https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS"
/** A simple endpoint method that takes a name and says Hi back */
#ApiMethod(name = "sayHi")
public MyBean sayHi(#Named("name") String name) {
MyBean mModelClassObject = null;
String text = "";
try {
String line = "";
StringBuilder builder = new StringBuilder();
URL url = new URL("https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
while ((line = reader.readLine()) != null) {
// ...
builder.append(line);
}
reader.close();
text = builder.toString();
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
#Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
LOCAL WAY
The other way is taking the version above and skipping something like dropbox
/** A simple endpoint method that takes a name and says Hi back */
#ApiMethod(name = "sayHi")
public MyBean sayHi(#Named("name") String name) {
MyBean mModelClassObject = null;
String text = "JUST PASTE YOUR JSON CONTENTS HERE";
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
#Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
I don't know if this follows best practice but my project is working now.
I also included firebase's code for getting info. check out this answer to a question i asked recently on reading and writing to firebase.
EDIT
cleaned up version which doesnt throw errors
public class MyEndpoint {
private FirebaseOptions options;
private DatabaseReference ref;
private String serviceAccountJSON = "i took mine out for security reasons";
// create firebase instance if need be
private void connectToFirebase(){
if (options == null) {
options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(new ByteArrayInputStream(serviceAccountJSON.getBytes(StandardCharsets.UTF_8)))
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
}
if(ref == null) {
ref = FirebaseDatabase.getInstance().getReference();
}
}
/** A simple endpoint method that takes a name and says Hi back */
#ApiMethod(name = "sayHi")
public MyBean sayHi(#Named("name") String name) {
// always do this first
connectToFirebase();
MyBean mModelClassObject = null;
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
// get the info
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
#Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
// wait for it
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
mModelClassObject.setData(mModelClassObject.getData() + name);
return mModelClassObject;
}
}
Finally, I found the solution, Its written under the APIs and references section of Google App Engine in this link, that we need to add such files in the appengine-web.xml file under the <resource-files> tag, using <include path=""/> property. After doing so its works for me. I placed the .json file containing project credentials in the WEB-INF directory and then entered its relative path in <resource-files> tag.
I have list of web pages(over 100) with I have to vistit and collect data from.
I decided to save the html from all of them to one file, and then use Jsoup to find the interesting data.
But problem is to I do not know how to run 100 threads, and save the responses into one file, any ideas?
maybe it's not a masterpiece, but it works, and I wanted to make it as simple as possible.
ArrayList<String> links = new ArrayList<>();
Elements myDiv;
private void saveDetails() throws IOException {
if(repeat < links.size()){
repeat++;
textView.setText(String.valueOf(repeat));
saveFile(myDiv.toString());
myDiv = null;
getDetails(links.get(repeat));
}else {
textView.setText("finished");
}
}
private void getDetails(String urlStr) {
final String detailsUrl = urlStr;
new Thread() {
#Override
public void run() {
Message msg = Message.obtain();
try {
Document doc = Jsoup.connect(detailsUrl).get();
myDiv = doc.select(".exhibitor-contact");
} catch (IOException e1) {
e1.printStackTrace();
}
detailsHandler.sendMessage(msg);
}
}.start();
}
private Handler detailsHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
saveDetails();
} catch (IOException e) {
e.printStackTrace();
}
}
};
You don't need to save all of them in a file and then process them. You can gather information one by one. It is my suggestion:
arrayList urls = {100 site-url}; //in correct syntax
Document doc = null;
for (String url : urls) {
doc = Jsoup.connect(url).get();
//now proccess doc.toString as you want(in regular expression for example)
//save your desired information
}
I'm trying to make my program save it's current state on internal memory so i can retrieve it when it loads up next time.
But it seems like i can't get it to work, my app keeps crashing on boot.
private File statoContatori = new File(getFilesDir(), "statoContatori");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inizializeCounters();
}
private void inizializeCounters() {
Scanner in = null;
try {
in = new Scanner(statoContatori);
while (in.hasNext())
{
String idContatore = in.next();
String nomeContatore = in.next();
String valore = in.next();
if (idContatore.equals("contatore_1"))
{
initializeContatore(R.id.contatore_1_label, R.id.contatore_1, nomeContatore, valore);
}
else if (idContatore.equals("contatore_2"))
{
initializeContatore(R.id.contatore_2_label, R.id.contatore_2, nomeContatore, valore);
//There are a couple more IFs in here...
}
} catch (FileNotFoundException e) {
creaFileStatoContatori();
}
finally {
in.close();
}
}
private void creaFileStatoContatori() {
PrintWriter out = null;
try {
out = new PrintWriter(statoContatori);
out.println("contatore_1\tcontatore_1\t0");
out.println("contatore_2\tcontatore_2\t0");
out.println("contatore_3\tcontatore_3\t0");
out.println("contatore_4\tcontatore_4\t0");
out.println("contatore_5\tcontatore_5\t0");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
finally {
out.close();
}
inizializeCounters();
}
So basically what i'm trying to do is:
If the file is present -> load the file
If the file is not present -> create the file with standard configs -> load the file
What am i doing wrong?
in my application I'm trying to access node created on server using smack library.When i run the code in java it does not give me any error.But when i try the same using android project at that time lo-gin is successful but while accessing node it's giving me error 404.
I have added Asmack jar file in build path.Please help me...I'm stuck...
public class ChatApplicationActivity extends Activity {
/** Called when the activity is first created. */
static XMPPConnection connection;
TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView=(TextView)findViewById(R.id.textView);
try {
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
ConnectionConfiguration cc = new ConnectionConfiguration("192.168.1.113", 5222, "192.168.1.113");
connection = new XMPPConnection(cc);
connection.connect();
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
connection.login("test","test");
Log.i("debug", "login success");
// MySmackClient client=new MySmackClient();
// client.login("test1","test1");
//client.displayBuddyList();
// CreateNode node = new CreateNode(connection);
subNode("test#eze-dem-113","testNode5");
// String talkTo = br.readLine();
System.out.println("-----");
// System.out.println("All messages will be sent to " + talkTo);
System.out.println("Enter your message in the console:");
System.out.println("-----\n");
} catch (XMPPException e) {
e.printStackTrace();
}
}
public void subNode(String JID,String nodeName)
{
PubSubManager mgr = new PubSubManager(connection);
// String pubSubAddress = "pubsub." + connection.getServiceName();
// PubSubManager manager = new PubSubManager(connection, pubSubAddress);
try {
// Get the node
// Node eventNode = manager.getNode("testNode5"); //i always get error here
LeafNode node = (LeafNode)mgr.getNode(nodeName);
node.addItemEventListener(new ItemEventCoordinator());
node.subscribe(JID);
} catch (XMPPException e) {
e.printStackTrace();
}
}
class ItemEventCoordinator implements ItemEventListener
{
int track =0;
public void handlePublishedItems(ItemPublishEvent items)
{
System.out.println("Got Publish:"+track);
PayloadItem<SimplePayload> item = (PayloadItem<SimplePayload>) items.getItems().get(0);
SimplePayload payload = item.getPayload();
String payloadData = payload.toXML();
System.out.println(payloadData);
}
}
}
What version of Smack are you using. I don't think asmack is being maintained, so it is probably out of sync with Smack proper.
One suggestion would be to change
PubSubManager mgr = new PubSubManager(connection);
for the lines you have commented out
String pubSubAddress = "pubsub." + connection.getServiceName();
PubSubManager manager = new PubSubManager(connection, pubSubAddress);
Smack was changed to default to that pubsub address, asmack probably doesn't have that change. If you use the more explicit constructor, it will be consistent in both environments.