Android - large data json download - android

I'm facing a problem in my app Android that consists in a failure to recover large json data from web service. The JSON data is large because contains images which are recovered from a table in my database.
Some days ago everything was working fine, but the number of registers in this table grew up fastly and then the problem rises.
This problem is not happening on iOS or on Android emulator, just on real Android device.
The code is stopping the download suddenly and throwing the error
org.json.JSONException: Unterminated string at character <cccc> of <json data>
That is, the code is not downloading the entire JSON data. Besides, the download stops in a different point always I run the code.
Someone know why that is happening?
This is the function which tries to recover the data from web service:
protected static JSONObject executeJSONQuery(ContentValues values,
WebServiceResolverCode code, Context context)
throws ContratoInativoException, JSONException {
URL url;
HttpURLConnection conn;
JSONObject jArray = null;
// build the string to store the response text from the server
String response = "";
try {
url = new URL(WebServiceResolver.getWebServiceSufix(code, context));
String param = "";
for (String key : values.keySet()) {
Object value = values.get(key);
param += key+"="+ URLEncoder.encode(value!=null?values.getAsString(key):"", "UTF-8")+"&";
}
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setFixedLengthStreamingMode(param.getBytes().length);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// send the POST out
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(param);
out.flush();
out.close();
// start listening to the stream
Scanner inStream = new Scanner(conn.getInputStream());
while (inStream.hasNextLine()){
response += (inStream.nextLine());
}
inStream.close();
// process the stream and store it in StringBuilder
jArray = new JSONObject(response);
} catch (IOException ex) {
ex.printStackTrace();
Log.d("ERROR JSON STRING", response);
}
return jArray;
}

Firstly, do not keep an image in a table. Keep it in your server space and keep the URL to the image in your table. When you need to load the image, load it with the URL kept in the table.
Secondly, JSON is a light weight data interchange format. You should limit the number of items it carries. Its advisable not to let it carry up to a hundred rows in your table(when converting to JSON). If you have to, then load a little at first, then load another little, till it gets to the end. That's the idea behind infinite scrolling.
That way, it loads your data efficiently.

Looks like your json string object is not forming correctly. It may be missing s double quote at the end of a string. Check the param string object.

Related

Most optimal way to load large JSON into a List<>

I am working on android multiplayer game. My JSON file contains 800 000+ dictionary words. JSON array is being loaded in List once players enter GameActivity to actually play game. So each time player starts 1vs1 game, JSON is being loaded into a List<>.
Now, I have 2 options:
Load JSON the most optimal way so user does not get out of memory error after a while
Load JSON file into a List<> only once, when application is open.
I'm not sure about any of these 2 cases, can someone give me a hand on how to do this please? Thank you
I can't comment because of my repu.
But you can try to few different approaches into this problem.
If your JSON changes very rarely i can suggest this method.
You can put your json inside your asset file. and call in runtime with this
public String loadJSONFromAsset() {
String json = null;
try {
InputStream is = getActivity().getAssets().open("yourfilename.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
Or you can fetch your Json before app starts and store in ContentProvider (DB or SharedPreference). And this way you only fetch your json when it is necessary.
//right before fetching JSON
boolean thereIsAnyUpdatesInJSON = checkYourDictionaryJsonIfThereAreAnyUpdates();
if(!isDictionaryDatabaseAvailable && thereIsAnyUpdatesInJSON){
fetchYourDictJson();
}

Youtube Get uploaded video list. FileNotFound Error

I am trying to get list of videos uploaded on my YouTube channel using following
https://www.googleapis.com/youtube/v3/search?part=snippet&channelId{MY_CHANNEL_ID}&maxResults=50&key={MY_APP_ID}
I have created App in Google App Console and generate APP ID for the same. But when I trying to access it through my Android application getting java.io.FileNotFoundException error
I have given application identifier and SHA1 also, If I try to access through Web Browser key without any other constrains it works well and returns all the video list but in case of Android it is not working.
#Override
protected String doInBackground(Void... voids) {
HttpURLConnection urlConnection = null;
String urlString = "https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCrF362wkcVnjqqPRsSEzvgg&maxResults=50&key=AIzaSyAiAFjZb1eVdRxVWnymrhuAb1iDlmYupu8";
//urlString = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=PLTqSMwQKOhUhl7gm7h6YwX6XPYr0ViBtu&key=AIzaSyAiAFjZb1eVdRxVWnymrhuAb1iDlmYupu8";
String jsonString = new String();
URL url = null;
try {
url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setDoOutput(true);
urlConnection.connect();
BufferedReader br=new BufferedReader(new InputStreamReader(url.openStream()));
char[] buffer = new char[1024];
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
jsonString = sb.toString();
System.out.println("JSON: " + jsonString);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonString;
}
Error Log
BasicNetwork.performRequest: Unexpected response code 403 for https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCrF362wkcVnjqqPRsSEzvgg&maxResults=50&key=AIzaSyAiAFjZb1eVdRxVWnymrhuAb1iDlmYupu8
05-13 15:28:26.607 19118-19151/com.jeevanmulmantra W/System.err: java.io.FileNotFoundException: https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCrF362wkcVnjqqPRsSEzvgg&maxResults=50&key=AIzaSyAiAFjZb1eVdRxVWnymrhuAb1iDlmYupu8
Without looking at your API Console settings, I cannot say for sure. But from looking at the HTTP response, it looks like your IP address might be blocked by the Google authorization server. Hence, it is sending you back an unauthorized request HTTP status code 403.
Go to your API Console and select the None radio button from under the Key restrictions section. Then try again. It should work.
This is not exactly what you are asking but I will share my experience.
I had a similar situation a couple of months ago. Seaching on line I got to the conclusion that the YouTube api option for Android just doesn't work. I ended up with a more convenient solution for my development:
I got a YT api key for a website and bound it to the corresponding domain.
I Created a php file that gets the playlist from youtube twice a day using curl and cron job setup on the server. The playlist file in json format is then written to the web server (refreshed twice a day).
The Android app connects to my server intead of YTs and get the "cached" json play list from there.
This option drastically reduces the impact on the quota consumption because all the hits to the playlist go to the website.
If you are interested in this option I can share the php used for getting the play list.
I had the same problem, just regenerate another key and restrict it again with the package name and SHA1 from your Android Studio. It wasn't working with the old key regenerating the key and restricting it again worked for me.

Rails RESTful API connection with android

Hi i have been learning rails for a bit , now i need to make some mobile applications android & IOS connecting to my webapp, I know that the API is used to make the connections like the endpoints / url and then the methods for each and everyone of them is used to make it, my problem how can i know or test that my API for the mobile is working properly?
I am currently doing the android par and i don't know where to start with that. can guys also help with pointing out where to learn them, i mean creating user's in my webapp , I used device so i need to make an android application to make user's , insert data into my PG(postgresql) , get some geolocaion (geocoder), from the webapp , but i don't know where to start with the android how to send and get data from that, also how to test if the API that i made is working properly....
any help willbe greatly appreciated specially links to tutorials for rails version 4.+
I'm showing you the simplest way to do this things.
First make a json formatted api using rails. And you can make a URL that can accept GET method value(www.exmp.com?val=asd).
In your android application make a Class name JsonParser.
copy and paste the following code.
private String jsonurl;
public JsonParser(String url) {
this.jsonurl = url;
}
public String fetchJSON(){
try {
URL url = new URL(jsonurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(25000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
String data = convertStreamToString(stream);
return data;
} catch (Exception e) {
Log.d("Check", e.getMessage());
return null;
}
}
private String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
After that make a Object of that class in a Asynctask thread. and also give the URL as a parameter.you will get the Json formatted data.
To get the actual data you need to make a JSONObject type object and call like this .
JSONObject reader = new JSONObject(jsonData); // returning json formatted data
this.status = reader.getString("status");
Now you can make java Bean to get or set the value for further uses.

ANDROID: JSONArray save in Internal Storage to work without internet conection

I have a PHP JSON that sends me JSONArray.
public JSONArray lastTweet()throws ClientProtocolException,IOException,JSONException{
StringBuilder url = new StringBuilder(URL);
HttpGet get = new HttpGet(url.toString());
HttpResponse r = client.execute(get);
int status = r.getStatusLine().getStatusCode();
if(status == 200){
HttpEntity e = r.getEntity();
String data = EntityUtils.toString(e);
JSONArray timeline = new JSONArray(data);
return timeline;
}
return null;
}
I can get Object and values from this JSONArray (timeline), but it work only then application have internet conection. I want to save this JSON in my internal storage like a json file and after work with this file in offline mod. How i can do this?
Try using JSON Simple library which allows easy encoding/decoding of JSON files.
Examples: Encoding
Then it's just plain:
try {
outStream = openFileOutput("tweet.json", Context.MODE_PRIVATE);
outStream.write(json.getJSONString().getBytes());
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
However if you do not want to store it for forever, or for re-sending purposes, I recommend using Cache
Mind that cache can be automatically wiped, so it's up to you. More on this, as always, on the Android developers site: Android: Saving Files # Write Internal Storage
UPDATE:
Turns out that android JSONObject.toString() produces coherent JSON output that can be saved to a file the way desciber above, without any 3rd party library, however you would need to marshall it back to JSONObject/Array/Primitive by yourself, and that will take some extra work.

Send JSON request - JQuery analog

I need to send a JSON request similar to jQuery's ajax method.
The official documentation quote on the data parameter says:
If value is an Array, jQuery serializes multiple values with same key based on the value of the traditional setting
So I have the same situation - a key that maps to an array "parameters":[123123, {"category":"123"}]
The complete data parameter looks like
$.ajax({
url: "/api/",
data: {"parameters":[123123, {"category":"123"}], "anotherParameter":"anotherValue"}
Would you mind telling how to achieve the same functionality in Java ?
UPD:
I've made it to work with the use of gson + collections + post request.
Here're some guide lines:
Sending POST requests in JAVA.
You might also want to consider performance issues related to different kinds of json parsers
What have you tried so far and what exactly is the problem? Is it that you don't know how to create a connection, that you don't know how to serialize your objects or that you don't know how to make the thing run asynchronously?
I don't think Java has any asynchronous HTTP call methods, you need to use a regular URLConnection and run it in a separate thread. The connection itself is formed like this:
URL url = null;
URLConnection urlConnection = null;
String myURL = "http://example.com/ajax.php?foo=bar";
try {
url = new URL(myURL);
urlConnection = url.openConnection();
} catch (Exception e) {
e.printStackTrace();
return;
}
InputStream responseStream = null;
try {
responseStream = urlConnection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
return;
}
Then you must use something like the AsyncTask class to make it a background job.
For converting your objects to JSON you might want to use the GSON library.

Categories

Resources