data not passing when running doInBackground method within for loop - android

I have some pics to upload to the ftp server and I am using Asynctask for it.The images need to be sent to multiple host so I am using a for loop.The data to be passed is very well being fetched by the constructor but the doInBackground method is not running which was earlier running very well without the for loop and the additional data apart from the String filePathName that I am trying to pass in now in doInBackground.please help me
class uploadTask extends AsyncTask<String, Void, String> {
public uploadTask(String filePathName,String host_2,String user_2,String pass_2)
{
filePath=filePathName;
host_1=host_2;
user_1=user_2;
pass_1=pass_2;
Toast.makeText(getBaseContext(),"FTP DATA RECEIVING:"+"HOST:"+host_2+" USERNAME:"+user_2+" PASS:"+pass_2,Toast.LENGTH_LONG).show();
//hostName=host;
}
#Override
protected String doInBackground(String... params) {
try {
Toast.makeText(getBaseContext(),"Entered Do in Background Method to upload",Toast.LENGTH_SHORT).show();
ftp_host = "ftp.photoshelter.com";//This is not the correct way. Supposed to get from Backendless table
ftp_username = "brytest";//This is not the correct way. Supposed to get from Backendless table
ftp_password = "passtest";//This is not the correct way. Supposed to get from Backendless table
Toast.makeText(getBaseContext(),"HOST:"+ftp_host+" USERNAME:"+ftp_username+" PASS:"+ftp_password,Toast.LENGTH_LONG).show();
news_agency = "news agency";
easyFTP ftp = new easyFTP();
ftp.connect(ftp_host, ftp_username, ftp_password);
status = ftp.setWorkingDirectory("mem/images"); // if User say provided any Destination then Set it , otherwise
// Upload will be stored on Default /root level on server
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageTimeStamped = ftp_username + "_" + timeStamp + ".png";
FileInputStream is = new FileInputStream(imageFileLocation);
//addPhotoGrapherInfo();
ftp.uploadFile(is, imageTimeStamped);
System.out.println("Successfull ftp upload to " + ftp_host);
Toast.makeText(getBaseContext(), "Photo uploading by ftp to " + ftp_host, Toast.LENGTH_LONG).show();
//}
//reset booleans
//cameraPicTaken = false;
//galleryImageSelected = false;
//System.out.println("reset cameraPicTaken and galleryImageSelected");
// }
return new String("Upload Successful");
}catch (Exception e){
String t="Failure : " + e.getLocalizedMessage();
return t;
}
}
}
my onClickListener with for loop
if(cameraPicTaken || galleryImageSelected) {
Toast.makeText(SubmitActivity.this,"Image Location is:"+ imageFileLocation,Toast.LENGTH_LONG).show();
//addPhotoGrapherInfo();
for(int i=0;i<Common.selectedHostArray.size();i++) {
uploadFile(imageFileLocation,Common.selectedHostArray.get(i),Common.selectedUsernameArray.get(i),Common.selectedPasswordArray.get(i));
}
cameraPicTaken = false;
galleryImageSelected = false;
}
funnction called in onClick
public void uploadFile(String filePath,String host_1,String user_1,String pass_1)
{
if(cameraPicTaken == true) {
System.out.println("camera photo start upload");
//for(int i=0;i<Common.selectedHostArray.size();i++) {
//host_1=Common.selectedHostArray.get(i);
//user_1=Common.selectedUsernameArray.get(i);
//pass_1=Common.selectedPasswordArray.get(i);
//host_1="ftp.photoshelter.com";
//user_1="brytest";
//pass_1="passtest";
Toast.makeText(getBaseContext(),"FTP DATA PASSING:"+"HOST:"+host_1+" USERNAME:"+user_1+" PASS:"+pass_1,Toast.LENGTH_LONG).show();
new uploadTask(filePath,host_1,user_1,pass_1).execute();
// }
//cameraPicTaken = false;
//galleryImageSelected = false;
System.out.println("reset cameraPicTaken and galleryImageSelected");
//cameraPicTaken = false;
}
if(galleryImageSelected == true){
System.out.println("gallery image start upload");
Toast.makeText(getBaseContext(),"FTP DATA PASSING:"+"HOST:"+host_1+" USERNAME:"+user_1+" PASS:"+pass_1,Toast.LENGTH_LONG).show();
new uploadTask(filePath,host_1,user_1,pass_1).execute();
//new uploadTask(filePat)h.execute();
//galleryImageSelected = false;
}
Toast.makeText(getBaseContext(), "Photo uploading by ftp to photoshelter.com" /*+ news_agency*/, Toast.LENGTH_LONG).show();
}

You're trying to perform a UI command on a background thread (Toast). This is causing your background tasks to fail early. Since your background tasks catch their own errors, they fail silently.
#Override
protected String doInBackground(String... params) {
try {
// you can't Toast on a background thread, this should throw an exception
Toast.makeText(getBaseContext(),"Entered Do in Background Method to upload",Toast.LENGTH_SHORT).show();
...
}catch (Exception e){
// your Toast exception is getting caught silently here
String t="Failure : " + e.getLocalizedMessage();
return t;
}
}
By the way, the try/catch on everything is not a good practice. You end up with a ton of silent failures leaving you scratching your head and asking why things aren't working.

Related

Getting the calling fragment within an asynchronous task

Aim
In a fragment, I have a search bar which looks for online news about what the user typed. I would want to display these news (title + description + date of publication + ... etc.) in the GUI, as vertical blocks.
Implementation
Explanations
In the fragment, within the search event handling, I instanciated an asynchronous task and execute it with the good URL REST API I use to do the search.
In the asynchronous task, I make use of this REST API (thanks to the URL and some required parameters as an authorization key, etc.). When my asynchronous task gets answered, it must update the fragment's GUI (i.e.: it must vertically stack GUI blocks containing the titles, descriptions, etc. of the got news).
Sources
You will find sources in the last part of this question.
My question
In the asynchronous task (more precisely: in its function that is executed after having got the answer), I don't know how to get the calling fragment. How to do this?
Sources
Fragment part
private void getAndDisplayNewsForThisKeywords(CharSequence keywords) {
keywords = Normalizer.normalize(keywords, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
new NetworkUseWorldNews().execute("https://api.currentsapi.services/v1/search?keyword=" + keywords + "&language=en&country=US");
}
Asynchronous task part
public class NetworkUseWorldNews extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String[] urls) {
StringBuilder string_builder = new StringBuilder();
try {
URL url = new URL(urls[0]);
HttpsURLConnection https_url_connection = (HttpsURLConnection) url.openConnection();
https_url
_connection.setRequestMethod("GET");
https_url_connection.setDoOutput(false);
https_url_connection.setUseCaches(false);
https_url_connection.addRequestProperty("Authorization", "XXX");
InputStream input_stream = https_url_connection.getInputStream();
BufferedReader buffered_reader = new BufferedReader(new InputStreamReader(input_stream));
String line;
while((line = buffered_reader.readLine()) != null) {
string_builder.append(line);
}
buffered_reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return string_builder.toString();
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject news_response_http_call = new JSONObject(result);
switch(news_response_http_call.getString("status")) {
case "ok":
JSONArray news = news_response_http_call.getJSONArray("news");
for(int i = 0; i < news.length(); i++) {
JSONObject a_news = news.getJSONObject(i);
String title = a_news.getString("title");
String description = a_news.getString("description");
String date_of_publication = a_news.getString("published");
String url = a_news.getString("url");
String image = a_news.getString("image");
System.out.println(title + ": " + date_of_publication + "\n" + image + "\n" + url + "\n" + description);
WorldNewsFragment world_news_fragment = ...;
}
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
If I am right, you want to update View of your caller Fragment. if FragmentA called service then FragmentA should be update.
However the approach you are asking is wrong. Instead of getting caller Fragment in your AsyncTask response. You should do it with Callback.
So now you will need to pass callback in AsyncTask. So instead of posting full code, here are already answers with this problem.
Finally your calling syntax will look like.
NetworkUseWorldNews task = new NetworkUseWorldNews(new OnResponseListener() {
#Override
public void onResponse(String result) {
// Either get raw response, or get response model
}
});
task.execute();
Actually I am still very unclear about your question. Let me know in comments if you have more queries.
Must checkout
Retrofit or Volley for calling Rest APIs
Gson for parsing JSON response automatically to models

Complete AsyncTask only when Firebase Task completes

How can I make an AsyncTask's doInBackground() only return when another async method completes?
On a high level, the Activity's purpose is to allow the user to upload a review. The review may also have images. Now in my code, I have two AsyncTasks: ImageCompressionTask and ImageUploadTask. Basically, once the user selects images to upload, ImageCompressionTask is executed for each image. In the onPostExecute() method of that task, ImageUploadTask is executed. The purpose of ImageUploadTask is to upload the compressed image and update the Firestore (database) with the download URL of the aforementioned uploaded image. Following is its code:
public class ImageUploadTask extends AsyncTask<byte[], Integer, Void> {
#Override
protected Void doInBackground(byte[]... bytes) {
StorageReference ref = App.getFireStorage().getReference();
ref = ref.child("review_images/" +
mDestinationId + "/" +
mExistingReview.getReviewId() + "/" +
mUploadProgressCount);
ref.putBytes(bytes[0]).addOnSuccessListener(taskSnapshot -> {
String url = taskSnapshot.getDownloadUrl().toString();
mExistingReview.getImages().add(url);
App.getFirestore().collection("reviews").document(mExistingReview.getReviewId()).set(mExistingReview);
mUploadProgressCount++;
});
return null;
}
}
However, the issue is that the doInBackground() returns prematurely. I understand WHY it happens (because the ref.putBytes() method runs asynchronously) but I want it to wait until ref.putBytes() finishes. How can I do that?
Can you please check it this way :
#Override
protected synchronized Void doInBackground(byte[]... bytes) {
StorageReference ref = App.getFireStorage().getReference();
ref = ref.child("review_images/" +
mDestinationId + "/" +
mExistingReview.getReviewId() + "/" +
mUploadProgressCount);
ref.putBytes(bytes[0]).addOnSuccessListener(taskSnapshot -> {
String url = taskSnapshot.getDownloadUrl().toString();
mExistingReview.getImages().add(url);
App.getFirestore().collection("reviews").document(mExistingReview.getReviewId()).set(mExistingReview);
mUploadProgressCount++;
});
return null;
}
i have solved this problem with ObservableInteger
is a listener that listen for values
private ObservableInteger mObsInt;
//Listener
mObsInt = new ObservableInteger();
mObsInt.set(0);
mObsInt.setOnIntegerChangeListener(new OnIntegerChangeListener()
{
#Override
public void onIntegerChanged(int newValue)
{
if (mObsInt.get()==1)
Log.e("Downloads"," mObsInt 1");
Log.e("Download1"," Finished first process ");
if (mObsInt.get()==2){
Log.e("Downloads"," mObsInt 2");
Log.e("Download2"," Finished second process ");
mProgressDialog.dismiss();
Intent mainIntent = new Intent().setClass(LoginActivity.this, Principal.class);
startActivity(mainIntent);
finish();
}
}
});
and then just do this (after a process has finished or an asynctask)
mObsInt.set(mObsInt.get()+1);
so it will count, if the first thing finish obsInt will be 1 , and when the second one finish, obsInt will be 2, so after obsInt == 2 , you can move on to the other activity or process you need
happy coding !
This can be accomplished with CountDownLatch:
public class ImageUploadTask extends AsyncTask<byte[], Integer, Void> {
#Override
protected Void doInBackground(byte[]... bytes) {
// Initialize CountDownLatch
final CountDownLatch signal = new CountDownLatch(1);
StorageReference ref = App.getFireStorage().getReference();
ref = ref.child("review_images/" +
mDestinationId + "/" +
mExistingReview.getReviewId() + "/" +
mUploadProgressCount);
ref.putBytes(bytes[0]).addOnSuccessListener(taskSnapshot -> {
String url = taskSnapshot.getDownloadUrl().toString();
mExistingReview.getImages().add(url);
App.getFirestore().collection("reviews").document(mExistingReview.getReviewId()).set(mExistingReview);
mUploadProgressCount++;
// Start count down
signal.countDown();
});
// Wait for putBytes to return and handle case if
// threads get interrupted.
// You can also specify a maximum time to wait before
// displaying error to user (ie Try Again)
try {
signal.await(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}

Android Google Saved Games unexpected conflicts

In my game I have in-game currency and I want to save its value to the cloud. I decided to use Google Saved Games API. Everything works great but when I'm saving data to the Snapshots and then reading it when the game launches again, I'm getting conflicts, even when I'm on the same device. Now I'm saving currency's state after every change, so when player spents or gets some "coins". I'm thinking that this could be very often and services can't handle it because when I'm offline (without connection to the network) everything works nice and fast but when I'm online (connected to Wi-fi) work with Snapshots is slower and as I said I'm getting conflicts with data last saved and previous data I saved (I'm loggging all values...). Sometimes I get even 5 conflicts. I have 3 functions to work with Saved Games. One for reading data, one for saving data and one for checking for conflicts:
Reading data:
private void readSavedGame(final String snapshotName) {
AsyncTask<Void, Void, Boolean> readingTask = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
Snapshots.OpenSnapshotResult result = Games.Snapshots.open(mGoogleApiClient, snapshotName, false).await();
Snapshot snapshot = processSnapshotOpenResult(result, 0);
if(snapshot != null) {
try {
updateGameData(snapshot.getSnapshotContents().readFully());
Log.d(TAG, "Updating game: "+String.valueOf(coins)+"...");
return true;
} catch (IOException e) {
Log.d(TAG, "Error: " + e.getMessage());
}
}
return false;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if(result) Log.d(TAG, "Game state read successfully...");
else Log.d(TAG, "Error while reading game state...");
updateUi();
}
};
readingTask.execute();
}
Saving data:
private void writeSavedGame(final String snapshotName, final byte[] data) {
AsyncTask<Void, Void, Boolean> updateTask = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
Snapshots.OpenSnapshotResult result = Games.Snapshots.open(
mGoogleApiClient, snapshotName, false).await();
Snapshot snapshot = processSnapshotOpenResult(result, 0);
if(snapshot != null) {
snapshot.getSnapshotContents().writeBytes(getGameData());
Log.d(TAG, "Saving: "+String.valueOf(coins)+"...");
Snapshots.CommitSnapshotResult commitSnapshotResult = Games.Snapshots.commitAndClose(mGoogleApiClient, snapshot, SnapshotMetadataChange.EMPTY_CHANGE).await();
if(commitSnapshotResult.getStatus().isSuccess()) return true;
}
return false;
}
#Override
protected void onPostExecute(Boolean result) {
if (result) Log.d(TAG, "Game was saved successfully....");
else Log.d(TAG, "Error while saving game state...");
}
};
updateTask.execute();
}
Checking for conflicts or handling OpenSnapshotResult
Snapshot processSnapshotOpenResult(Snapshots.OpenSnapshotResult result, int retryCount) {
Snapshot mResolvedSnapshot = null;
retryCount++;
int status = result.getStatus().getStatusCode();
Log.i(TAG, "Save Result status: " + status);
if (status == GamesStatusCodes.STATUS_OK) {
Log.d(TAG, "No conflict, SNAPSHOT is OK");
return result.getSnapshot();
} else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) {
return result.getSnapshot();
}
else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONFLICT) {
Log.d(TAG, "Conflict: "+String.valueOf(retryCount));
Snapshot snapshot = result.getSnapshot();
Snapshot conflictSnapshot = result.getConflictingSnapshot();
// Resolve between conflicts by selecting the newest of the conflicting snapshots.
mResolvedSnapshot = snapshot;
if (snapshot.getMetadata().getLastModifiedTimestamp() <
conflictSnapshot.getMetadata().getLastModifiedTimestamp()) {
mResolvedSnapshot = conflictSnapshot;
}
try {
Log.d(TAG, "Snapshot data: "+new String(snapshot.getSnapshotContents().readFully()));
Log.d(TAG, "Conflicting data: "+new String(conflictSnapshot.getSnapshotContents().readFully()));
} catch (IOException e) {
Log.e(TAG, "ERROR WHILE READING SPAPSHOTS CONTENTS...");
}
Snapshots.OpenSnapshotResult resolveResult = Games.Snapshots.resolveConflict(
mGoogleApiClient, result.getConflictId(), mResolvedSnapshot).await();
if (retryCount < MAX_SNAPSHOT_RESOLVE_RETRIES) {
// Recursively attempt again
return processSnapshotOpenResult(resolveResult, retryCount);
} else {
// Failed, log error and show Toast to the user
String message = "Could not resolve snapshot conflicts";
Log.e(TAG, message);
//Toast.makeText(getBaseContext(), message, Toast.LENGTH_LONG).show();
}
}
// Fail, return null.
return null;
}
Conflict principes are explained nicely here.
My code is based on official docs implementations and samples.
So when offline, everything works excellent but when connected, I'm getting conflicts on the same device... Maybe I'm updating my saved game very often and services can't handle it. Any ideas? Thanks.
As discussed in Saved Games - Conflict resolution
Typically, data conflicts occur when an instance of your application is unable to reach the Saved Games service while attempting to load data or save it. In general, the best way to avoid data conflicts is to always load the latest data from the service when your application starts up or resumes, and save data to the service with reasonable frequency.
In addition to that, it is also recommended to follow Best practices for implementing saved games to deliver the best possible product to your players.
Also, to learn how to implement Saved Games for your platform, see the resources given in Client implementations.

is it safe to use ThreadPoolExecutor inside AsyncTask doInBackground

I have to download a Json with a list of files, and then parallel download the files in the list. I would like to update periodically the ProgressDialog, so I implemented in this way
I create and show the dialog
I start an AsyncTask
onProgressUpdate receives 2 Integers, current progress and max progress, and updates the progress bar
doInBackground
downloads the json file and obtains the list of files to download
creates a ThreadPoolExecutor (tpe), with a LinkedBlockingQueue<Runnable>
submit a runnable for each file, that download the file to disk using Apache commons-io FileUtils.copyURLToFile
exec shutdown
in a while cycle. tpe.awaitTermination(1, TimeUnit.SECONDS) invokes periodically publishProgress( (int) tpe.getCompletedTaskCount(), tot), to update the progress bar
onPostExecute hides and dismisses the progres bar, and manages the files downloades
is there any problem in using ThreadPoolExecutor inside an AsynTask?
I am discussing with a colleague who claims that there could be problems in the threads management, that could deadlock, and that might give us problems on future versions
that's the code
public static void syncFiles(...)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
sWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
sWakelock.acquire();
sProgress = new ProgressDialog(context);
sProgress.setCancelable(false);
sProgress.setTitle("MyTitle");
sProgress.setMessage("Sincronizzazione in corso");
sProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
sProgress.setIndeterminate(false);
sProgress.show();
sCurrentTask = new AsyncTask<Void, Integer, Manifest>()
{
#Override
protected void onCancelled()
{
if ((sProgress != null) && sProgress.isShowing())
sProgress.dismiss();
if ((sWakelock != null) && sWakelock.isHeld())
sWakelock.release();
};
#Override
protected Manifest doInBackground(Void... params)
{
ArrayList files = getFiles(....)// download the jsonfile, and return the list of files
final String baseurl = ... // get the remote base url
final String baselocal = ... //get the local base path ;
int tot = m.size();
publishProgress(0, tot);
final int MAX_THREADS = Runtime.getRuntime().availableProcessors(); * 4;
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
MAX_THREADS,
MAX_THREADS,
1,
TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>()
);
for (final String s: files)
{
tpe.submit(new Runnable()
{
#Override
public void run()
{
try
{
URL remoteUrl = new URL(baseurl + s);
File localUrl = new File(baselocal, s);
FileUtils.copyURLToFile(remoteUrl, localUrl, 60000, 60000);
Log.w(TAG, "Downloaded " + localUrl.getAbsolutePath() + " in " + remoteUrl);
} catch (Exception e)
{
e.printStackTrace();
Log.e(TAG, "download error " + e);
// error management logic
}
}
});
}
tpe.shutdown();
int num = 0;
publishProgress(num, tot);
try
{
while (!tpe.awaitTermination(1, TimeUnit.SECONDS))
{
int n = (int) tpe.getCompletedTaskCount();
Log.w(TAG, "COUTN: " + n + "/" + tot);
if (n != num)
{
num = n;
publishProgress(num, tot);
}
}
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return m;
}
protected void onProgressUpdate(Integer... prog)
{
if (sProgress.getMax() != prog[1]) {
sProgress.setMax(prog[1]);
}
sProgress.setProgress(prog[0]);
}
#Override
protected void onPostExecute(Manifest result)
{
sWakelock.release();
sProgress.hide();
sProgress.dismiss();
// manage results
}
}.execute();
}
If you'll checkout the implementation of AsyncTask then youi can find that AsyncTask itself has ThreadPool so it will start the task on separate thread. Acutually when we can the .execute() to start the background task this method is typically used with THREAD_POOL_EXECUTOR to allow multiple tasks to run in parallel on a pool of threads managed by AsyncTask. So why you need to implement another.
Update
Read about executeOnExecutor in this may be this can help you... It clearly says that if you are allowing multiple tasks to run in parallel from a thread pool is generally not what one wants, because the order of their operation is not defined....but here you want to download the files so I don't think the order is important so in my view you can use it and it'll not create any issue.

Updating a ContentProvider's underlying SQLite database from internet resource

I have a implemented a ContentProvider to serve up a list of geographical locations from an underlying SQLite database.
These locations are actually an output from a model and are available online in the form of a simple JSON string; I don't want to keep downloading them every time the app is started, so I want to store them locally in a database and update them at pre-defined intervals (once a day for instance).
My question is, where should I implement the downloading and parsing code? Should it be part of my ContentProvider implementation? Or part of the SQLiteOpenHelper implementation?
I started to implement it as a public function called updateSiteList in my ContentProvider, but I don't know how to actually call it (the ContentProvider is usually acessed indirectly via CursorLoader)!
I am bit stuck as to how to progress!
Can anyone point me in the right direction?
Thanks!
There are a couple of ways to achieve this.
The two most common ways I use are :-
1) a custom sync adapter.
2) An intent service.
With option 1 you get the benefit of the Android system handling network connection problems and is the recommended approach by the android Developers
With option 2 you get more control over when the data gets downloaded which may or may not be the best time for the user or the Android System.
Either way the solution is the same. At some point in time you will be making, in a background service, an HTTP get request to a url. when your request completes you will need to heck the status of the response and if appropriate you would then make a call to the content provider to wither insert or update your data accordingly. whichever approach you take this part will be the same.
Some further reading for you.
https://sites.google.com/site/andsamples/concept-of-syncadapter-androidcontentabstractthreadedsyncadapter
Be sure to watch that Google I/O video
Regardless of the approach you take, the code to download json and insert to your content provider could look something like this in an IntentService called from either your sync adapter or from somewhere within your app if not using a sync adapter.
public class ServiceInitialiseData extends IntentService {
static final String TAG = "ServiceSyncData";
//ACTION should include application package convention, just to show that this can
//be any string
public static final String SYNC_COMPLETED_ACTION="com.pjmobile.games.fantasyf1.SyncCompleted";
public ServiceInitialiseData() {
super("InitialiseDataService");
}
#Override
protected void onHandleIntent(Intent intent) {
String sJson;
try {
sJson = downloadFromServer("Some parsed url");
int i, x;
boolean res = false;
List <ContentValues> bulkValues = new ArrayList <ContentValues>();
JSONArray entries;
try {
entries = new JSONArray(sJson);
ContentValues cvEntity = null;
JSONObject entity;
x = entries.length();
for (i=0;i<x;i++){
entity = entries.getJSONObject(i).getJSONObject("some_json_key");
bulkValues.add(cvEntity);
}
}
int qCount = getContentResolver().bulkInsert(uri,
(ContentValues[])bulkValues.toArray(new
ContentValues[bulkValues.size()]));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
private String downloadFromServer(String url) throws ClientProtocolException, IOException {
HttpResponse sJson = getJSONEntityFromURL(this, url);
return EntityUtils.toString(sJson.getEntity());
}
private static HttpResponse getJSONEntityFromURL(Context context, String url) throws ClientProtocolException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
httpget.addHeader("Accept", "application/json");
httpget.addHeader("Content-Type", "application/json; charset=UTF-8");
HttpResponse response;
response = httpclient.execute(httpget);
return response;
}
For the above to work you would have to ode up the bulk insert method of your content provider which could look something like this
#Override
public int bulkInsert(Uri uri, ContentValues[] values) {
final SQLiteDatabase db = mDB.getWritableDatabase();
final int match = sURIMatcher.match(uri);
int numInserted= 0;
// Util.log_debug_message("#### URI MATCH - " + match);
switch(match){
case TEAMS:
numInserted = insertTeams(db, values);
break;
default:
throw new UnsupportedOperationException("unsupported uri: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null, false);
return numInserted;
}
private int insertTeams(SQLiteDatabase db, ContentValues[] values) {
int numInserted = 0;
db.beginTransaction();
try {
//standard SQL insert statement, that can be reused
SQLiteStatement insert =
db.compileStatement(INSERT_OR_REPLACE_STRING + TeamModel.TEAM_TABLE_NAME
+ "(" + TeamModel.COL_SERVER_ID
+ "," + TeamModel.COL_BONUS_RACE_ID
+ "," + TeamModel.COL_POINTS
+ "," + TeamModel.COL_POSITION
+ "," + TeamModel.COL_TEAM_NAME + ")"
+" values " + "(?,?,?,?,?)");
for (ContentValues value : values){
//bind the 1-indexed ?'s to the values specified
insert.bindString(1, value.getAsString(TeamModel.COL_SERVER_ID));
insert.bindString(2, value.getAsString(TeamModel.COL_BONUS_RACE_ID));
insert.bindString(3, value.getAsString(TeamModel.COL_POINTS));
insert.bindString(4, value.getAsString(TeamModel.COL_POSITION));
insert.bindString(5, value.getAsString(TeamModel.COL_TEAM_NAME));
insert.execute();
}
db.setTransactionSuccessful();
numInserted = values.length;
} finally {
db.endTransaction();
db.close();
}
return numInserted;
}
This is not a copy and paste solution. Merely an example stripped out of one of my apps and you should look at each line of code and take great care to understand what is going on.

Categories

Resources