1

Hey I have some problems with the my Android CouchDB project.

I use Volley for my Network Requests in Android.

The problem is that I don't get the full JSON Data back. The url for the Request is:

myserveradress:databaseport/databasename/documentname/

the response through the App is:

{"ok":true,"id":"E-c5b6d7c16ecb41cd8dadaf3514c968","rev":"1-41f6abc7851b1ad60d169149c557e7fc"}

if I try exact the same URL thorugh my browser my response is right: {"_id":"E-c5b6d7c16ecb41cd8dadaf3514c968","_rev":"1-41f6abc7851b1ad60d169149c557e7fc","player":{"solvedPuzzels":[false,false,false,false,false],"triesPerPuzzel":[0,0,0,0,0]},"invites":[],"settings":{"gameTime":4,"numberOfPlayers":2,"puzzels":7}}

The weird thing is that I use this in more than one requests in my app and in some it works pretty well.

HERE MY CODE: Fist I have a Helper Class for the Volley Requests:

public class NetworkVolley {

public static JsonObjectRequest POST(String url, final JSONObject json, Response.Listener listener){
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.PUT
            , url,json, listener,
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Volley", "onErrorResponse: ", error );
                    Log.e("Volley", "onErrorResponse: "+new String(error.networkResponse.data, StandardCharsets.UTF_8) );
                }
            })
    {

        @Override
        public Map<String,String> getHeaders()throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            params.put("Accept-Charset", AppConfig.CHARSET);
            params.put("Content-Type", "application/json");
            params.put("Accept","application/json");
            String encoding =  Base64.encodeToString(AppConfig.SERVER_COUCHDB_AUTHENIFICATIONDATA.getBytes(Charset.forName("utf-8")), Base64.DEFAULT);
            params.put("Authorization","Basic "+ encoding);;
            return params;
        }

        @Override
        public byte[] getBody() {
            return json.toString().getBytes();
        }

    };

    return request;
}


public static JsonObjectRequest GET(String url, Response.Listener listener){
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
            listener,
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Volley User", "onErrorResponse: ", error);
                }
            }) {

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            params.put("Accept-Charset", AppConfig.CHARSET);
            params.put("Content-Type", "application/json");
            params.put("Accept", "application/json");
            String encoding = Base64.encodeToString(AppConfig.SERVER_COUCHDB_AUTHENIFICATIONDATA.getBytes(Charset.forName("utf-8")), Base64.DEFAULT);
            params.put("Authorization", "Basic " + encoding);
            ;
            return params;
        }
    };
    return request;
}

}

And here is my Fragment:

@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    rootView = inflater.inflate(R.layout.fragment_invite, container, false);
    listView = (ListView) rootView.findViewById(R.id.listView);
    TV_numberOfPlayers = (TextView) rootView.findViewById(R.id.playerInfo);


    final InviteActivity activity = (InviteActivity) getActivity();
    numberOfPlayers = activity.getNumberOfPlayers();
    gameId = activity.getGameId();

    gameUrl = "myserveradress:databaseport/databasename/" + gameId + "/";

    userId = "userA";


    getFriendList();

    getGameObject();

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            JSONArray invites = new JSONArray();
            try {
                invites = object.getJSONArray("invites");
                for (int i=0;i<=invites.length();i++){
                    if (!(invites.length()==0) ||(!(invites.get(i).equals(parent.getItemAtPosition(position))))){
                        invites.put(parent.getItemAtPosition(position));
                        object.remove("invites");
                        object.put("invites", invites);
                        setInvite();

                    }else {
                        Log.i("Invite","Same invited Person");
                        break;
                    }
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });

    return rootView;
}

private void setInvite() {
    Response.Listener<JSONObject> POSTinvite = new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            getGameObject();
        }
    };
    Volley.newRequestQueue(getContext()).add(NetworkVolley.POST(gameUrl,object,POSTinvite));
}

private void getGameObject() {
    object = new JSONObject();
    Response.Listener<JSONObject> gameObjListener = new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            if (response!=null){
                object = response;
                Log.i("Game Obj", "onResponse: "+object);
                try {
                    TV_numberOfPlayers.setText(getString(R.string.inv_tv_invitetPlayers) + " " + object.getJSONArray("invites").length() + " / " + numberOfPlayers);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    Volley.newRequestQueue(getContext()).add(NetworkVolley.GET(gameUrl,gameObjListener));
}

private void getFriendList() {
    friendsearchUrl = "myserveradress:databaseport/databasename/_design/friendsearch/_view/friendsearch?key="+"\""+userId+"\"";

    friends = new ArrayList();

    Response.Listener<JSONObject> friendsListener = new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            try {
                for (int i=0;i<response.getJSONArray("rows").length();i++){
                    JSONObject object = new JSONObject(String.valueOf(response.getJSONArray("rows").get(i)));
                    friends.add(object.getString("value"));
                }
                adapter = new FriendsListAdapter(getActivity(),friends);
                listView.setAdapter(adapter);

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    };
    Volley.newRequestQueue(getContext()).add(NetworkVolley.GET(friendsearchUrl,friendsListener));
}

HERE THE LOGCAT:

I/Game Obj: onResponse: {"_id":"E-69329c12008541949cba062559a3e2","_rev":"1-b0b6eb597bfe6905b06723953fbf6870","player":{"solvedPuzzels":[false,false,false,false,false],"triesPerPuzzel":[0,0,0,0,0]},"invites":[],"settings":{"gameTime":4,"numberOfPlayers":2}}

Everything works fine to this point...

I/Game Obj: onResponse: {"ok":true,"id":"E-69329c12008541949cba062559a3e2","rev":"2-2e7fa50583c3dbd4eca8eaf103567da7"}
W/System.err: org.json.JSONException: No value for invites

The second output I cannot understand why I don't recive the full Data.

tobzilla90
  • 607
  • 5
  • 9
  • Could you show some code? Seems like you're creating a document in the first case. – Vyacheslav Gerasimov Aug 19 '16 at 19:36
  • I think there is a Problem with the Database but I will show some Code. I create the document in an other activity. Then I get the document and read it this works now after I but a backslash at the end of the URL before I received the wrong data. Then I change the document and save it after clicking an object in a listview. So far everything works now but then I need to get the data again from the database and it don't work but it is exactly the same method I call with the same URL the second time but I receive not the full data. – tobzilla90 Aug 19 '16 at 19:47
  • Could you trace the exact HTTP requests? The response through the App is not a document (not GET), but the type of response you get after a PUT or POST a new doc. (The IDs are different, too.) – pwagner Aug 20 '16 at 14:52
  • Yes the recived Request looks like one from an PUT or POST but actually it is a GET. I checked the Document ID the different ID's are a mistake in my Post here. In the programm the are the same. Sorry for that. I will add my Code to my Post now... – tobzilla90 Aug 20 '16 at 18:14
  • I doubt that it's CouchDB's fault, I guess that Volley is not really sending a GET request. Perhaps you could trace the actual HTTP request using something like WireShark, or check the CouchDB log. What's the difference between revisions 1 and 2 of doc E-69329c12008541949cba062559a3e2? – pwagner Aug 21 '16 at 07:28
  • The difference is that I save Data into the "invites" JSONArray in the Doc. I will have a try using the Volley Request without my own Helper class. If this also don't work I have no other idea what I can do to solve this – tobzilla90 Aug 21 '16 at 09:02

1 Answers1

2

I solved it !!!

The cache is the Problem...

Volley.newRequestQueue(getContext()).getCache().clear();

If i add this before I do the Volley GET Request

tobzilla90
  • 607
  • 5
  • 9