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.
Related
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
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.
I have a ListView that onLongClick it calls a method that is supposed to go out to a website, pull a jsonArray from it and then return information that is pulled from the array. However, when it calls the HttpURLConnection.connect() method it fails and goes to the catch block. When I use the getMessage() message on the exception it only returns Null. This is the second time in this program that I've connected to a URL in this same way and it works the first time perfectly. What could be causing this issue?
Here is the code for when the method is called:
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> a, View v, int pos, long id) {
String trainNum = list.getItemAtPosition(pos).toString();
String info = "hello";
try {
info = getCurrentTrainInfo(trainNum);
}catch(Exception e){
info = e.getMessage();
if(info == null)
info = "info is null";
tv.setText(info);
}
Toast.makeText(getApplicationContext(), info, Toast.LENGTH_LONG).show();
return true;
}
}
);
And here is the method getCurrentTrainInfo that is called in the try block above:
public String getCurrentTrainInfo(String num) throws IOException{
String sURL = "http://www3.septa.org/hackathon/RRSchedules/" + num;
URL url = new URL(sURL);
HttpURLConnection request2 = (HttpURLConnection) url.openConnection();
request2.connect();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonArray rootArr = root.getAsJsonArray();
int i = 0;
String acTime = "";
String station = rootArr.get(i).getAsJsonObject().get("station").getAsString();
String schTime = rootArr.get(i).getAsJsonObject().get("sched_tm").getAsString();
String esTime = rootArr.get(i).getAsJsonObject().get("est_tm").getAsString();
tv.setText(station);
String info = "Current Station: " + station + "\nScheduled leave time: " + schTime + "\nEstimated leave time: " + esTime;*/
return info;
}
Is there anything I can do to fix this problem?
I see your request is being made in the UI thread, you mentioned that in another moment used this same way and it worked, I believe this may have happened when you ran your application on a device/emulator with a version of Android prior to 3.0.
Within an Android application you should avoid performing long
running operations on the user interface thread. This includes file
and network access. StrictMode allows to setup policies in your
application to avoid doing incorrect things. As of Android 3.0
(Honeycomb) StrictMode is configured to crash with a
NetworkOnMainThreadException exception, if network is accessed in
the user interface thread.
You can create a AsyncTasks class and move the call request to it.
EDIT: tl;dr How do you insert into db using content resolver and simpleCursorAdapter without a listfragment hanging?
I have an AsyncTask that I am using to download JSON data. In onPostExecute() of that task I call handleNewMessageReponse() to update my Sqlite database with the results.
The code for handleNewMessageResponse()
private void handleNewMessagesResponse() {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
//Step 1. Ensure we got something back.
if (mMessagesResponse.getMessages().length > 0){
//Step 2. Delete all Message DB rows.
getActivity().getContentResolver().delete(EntegraContentProvider.CONTENT_URI_MESSAGES, null, null);
//Step 3. Populate DB with new info.
//Hangs UI here.
for (int i = 0; i < mMessagesResponse.getMessages().length; i++) {
Messages messages = mMessagesResponse.getMessages()[i];
ContentValues values = new ContentValues();
values.put("id", messages.getId());
values.put("parent", messages.getParent());
values.put("type", messages.getType());
values.put("user", messages.getUser());
values.put("subject", messages.getSubject());
values.put("body", messages.getBody());
values.put("datetime", messages.getDatetime());
values.put("status", messages.getStatus());
values.put("touched", messages.getTouched());
//Perform the Insert.
getActivity().getContentResolver().insert(
EntegraContentProvider.CONTENT_URI_MESSAGES, values);
mWasDataLoaded = true;
}
}
mDataListener.onDataFetchComplete();
}
});
}
This is all contained in a ListFragment which implements LoaderManager.LoaderCallbacks
The onCreate of this fragment looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] uiBindFrom = { "user", "subject" };
int[] uiBindTo = { R.id.messageUser , R.id.messageTitle };
getLoaderManager().initLoader(MESSAGES_LIST_LOADER, null, this);
adapter = new SimpleCursorAdapter(
getActivity(), R.layout.messages_list_item,
null, uiBindFrom, uiBindTo,
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(adapter);
}
Everything works great with one exception the below section of the code takes up to 10 seconds to execute and hangs the UI/List during the 10 seconds.
this section is when UI hangs:
//Step 3. Populate DB with new info.
for (int i = 0; i < mMessagesResponse.getMessages().length; i++) {
Messages messages = mMessagesResponse.getMessages()[i];
ContentValues values = new ContentValues();
values.put("id", messages.getId());
values.put("parent", messages.getParent());
values.put("type", messages.getType());
values.put("user", messages.getUser());
values.put("subject", messages.getSubject());
values.put("body", messages.getBody());
values.put("datetime", messages.getDatetime());
values.put("status", messages.getStatus());
values.put("touched", messages.getTouched());
//Perform the Insert.
getActivity().getContentResolver().insert(
EntegraContentProvider.CONTENT_URI_MESSAGES, values);
Can someone plese point me in the right direction and tell me what the standard approach to this seemingly common task is? This should be pretty simple but am having a hard time finding examples that fit my use case.
Thanks.
Here is my final code. Much more fluid:
private class EventsFetcher extends AsyncTask<String, Void, EventsResponse> {
private static final String TAG = "EventsFetcher";
#Override
protected EventsResponse doInBackground(String... params) {
EventsResponse returnResponse = null;
try {
//Create an HTTP client
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(mEventsBaseUrl);
//Perform the request and check the status code
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
try {
//Read the server response and attempt to parse it as JSON
Reader reader = new InputStreamReader(content);
Gson gson = new Gson();
returnResponse= gson.fromJson(reader, EventsResponse.class);
content.close();
} catch (Exception ex) {
Log.e(TAG, "Failed to parse JSON due to: " + ex);
failedGettingEvents();
}
} else {
Log.e(TAG, "Server responded with status code: " + statusLine.getStatusCode());
failedGettingEvents();
}
} catch(Exception ex) {
Log.e(TAG, "Failed to send HTTP POST request due to: " + ex);
failedGettingEvents();
}
return returnResponse;
}
#Override
protected void onPostExecute(EventsResponse resultResponse) {
EventsResultsHandler resultsHandler = new EventsResultsHandler();
resultsHandler.execute(resultResponse);
}
}
private class EventsResultsHandler extends AsyncTask<EventsResponse, Void, String> {
private static final String TAG = "EventsResultsHandler";
#Override
protected String doInBackground(EventsResponse... params) {
try {
EventsResponse evResponse = params[0];
//Step 1. Ensure we got something back.
if (evResponse.getEvents().length > 0){
//Step 2. Populate Array with new info.
List<ContentValues> jsonResults = new ArrayList<ContentValues>();
for (int i = 0; i < evResponse.getEvents().length; i++) {
Events events = evResponse.getEvents()[i];
ContentValues values = new ContentValues();
values.put("start_date", events.getStart_date());
values.put("end_date", events.getEnd_date());
values.put("name", events.getName().replace("'","''"));
values.put("location", events.getLocation().replace("'","''"));
values.put("summary", events.getSummary().replace("'","''"));
values.put("lat", events.getLat());
values.put("lng", events.getLng());
values.put("is_active", events.getIs_active());
values.put("hide_calendar_button", events.getHide_calendar_button());
values.put("hide_map", events.getHide_map());
jsonResults.add(values);
}
//Step 3. Delete all data in table.
getActivity().getContentResolver().delete(EntegraContentProvider.CONTENT_URI_EVENTS, null, null);
//Step 4. Insert new data via via Bulk insert.
getActivity().getContentResolver().bulkInsert(EntegraContentProvider.CONTENT_URI_EVENTS, jsonResults.toArray(new ContentValues[jsonResults.size()]));
mWasDataLoaded = true;
}
} catch(Exception ex) {
Log.e(TAG, "Failed to update results due to: " + ex);
failedGettingEvents();
}
return null;
}
#Override
protected void onPostExecute(String result) {
mDataListener.onDataFetchComplete();
}
}
You don't want to run the DB update on the UI thread since that will hang the UI as you saw.
But you method of updating is likely to cause the problems you are describing because you are using a cursor adapter.
You are effectively clearing the database and repopulating. If the cursor adapter gets to run before you have rewritten all rows you will see the result you are talking about in your second comment above.
You have two choices, the first is to load to memory, and then quickly swap the list adapters internal list by swapping a pointer to the list data in the adapter and then telling the list adapter that things changed. You have to do this swap on the UI thread but since it is just updating a pointer to the data it is fast and keeps the UI responsive. The downside is you have to have two copies of the data in memory to do the swap.
The second and perhaps harder is to change the way that you sync with the server so that you don't have to clear everything and reload everything, but rather are deleting, adding or modifying single records. I recommend this route but it is probably more work for you.
Hi Iam facing a hard time inserting data into salesforce objects , from my android app i want to insert data into a Sobject, implementing as below:
private void sendOrderRequest() throws UnsupportedEncodingException {
final String externalIdField = "OrderExtID__c";
final String externalId = "123";
final String accountType = SalesforceSDKManager.getInstance().getAccountType();
final LoginOptions loginOptions = SalesforceSDKManager.getInstance().getLoginOptions();
new ClientManager(getActivity(), accountType, loginOptions, SalesforceSDKManager.getInstance().shouldLogoutWhenTokenRevoked()).getRestClient(getActivity(), new RestClientCallback() {
#Override
public void authenticatedRestClient(RestClient client) {
if (client == null) {
SalesforceSDKManager.getInstance().logout(getActivity());
return;
}
// 'client' is a valid rest client.
RestRequest restRequest = null;
try {
HashMap<String, Object> fields = new HashMap<String, Object>();
fields.put(CREATEDBY, createdby.getText().toString());
fields.put(CREATEDDATE, createddate.getText().toString());
fields.put(ORDERID, orderid.getText().toString());
fields.put(PRODUCTID, productid.getText().toString());
fields.put(QUANTITY, quantity.getText().toString());
fields.put(PRICE, price.getText().toString());
fields.put(DESCRIPTION, description.getText().toString());
restRequest = RestRequest.getRequestForUpsert(getString(R.string.api_version), getString(R.string.objecttype),externalIdField,externalId, fields);
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// restRequest = RestRequest.getRequestForDescribeGlobal(getString(R.string.api_version));
client.sendAsync(restRequest, new AsyncRequestCallback() {
#Override
public void onSuccess(RestRequest request, RestResponse result) {
try {
System.out.println("successsss");
System.out.println("Result..printinf ===="+result.asJSONObject().getJSONArray("sobjects"));
EventsObservable.get().notifyEvent(EventType.RenditionComplete);
} catch (Exception e) {
onError(e);
}
}
i am getting error:404, can someone point me in right direction, the getRequestForUpsert() asks for externalIdfeild and external id, am i passing the request coreect way?..ant help is appreciated
If the problem is as stated, that your error message is suggesting that you have not provided an identified externalIdField nor an externalId, it is likely because you are attempting to perform an UPSERT operation via the REST request. An UPSERT is a Force.com Data Manipulation Language (DML) operation that will attempt to determine if the record (salesforce object) you are submitting is or is not already in the database by performing a lookup on its ID first. It allows such a lookup on either a salesforce ID (the record's PK) or an alternate candidate key field flagged as an ExternalId (typically from an external data table of record,) but also requires that you identify which field should be used as the key; the Id or an ExternalId field. If you only need to do an insert, try an alternate call to the getRequestForCreate() method instead. Below is a link to the REST documentation page for the RestRequest:
http://docs.developer.salesforce.com/docs/atlas.en-us.186.0.mobile_sdk.meta/mobile_sdk/android_native_classes_restrequest.htm