Android: Salesforce -cannot upsert data into object - android

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

Related

Android Google+ unable to get authorization code

I want to enable server-side Calendar API access for my android app.
I have followed the steps given here .
I am getting a null value for the authorization code.
I think I am giving wrong values for 'scope' field and the 'server_client_id' field.
Please give me an example showing correct fields values for 'scope' and 'server_client_id' in the getToken() method.
Thanks for any help.
PS- I have used google+ sign in for android given here for connecting to a google account.
EDIT- Here is my code. I have given the OAuth 2.0 scope for the Google Calendar API in the scope field.
I have taken Client ID for Android application from Developers Console and put in 'serverClientID' field. This is probably where I am wrong. I don't know how to get Server's Client ID which is required by the
public class AsyncGetAuthToken extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
Bundle appActivities = new Bundle();
appActivities.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,
"MainActivity");
String scopeString = "https://www.googleapis.com/auth/calendar.readonly";
String serverClientID = CLIENT_ID;
String scopes = "oauth2:server:client_id:" + serverClientID + ":api_scope:" + scopeString;
String code = null;
try {
code = GoogleAuthUtil.getToken(
MainActivity.this, // Context context
Plus.AccountApi.getAccountName(mGoogleApiClient), // String accountName
scopes, // String scope
appActivities // Bundle bundle
);
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
return null;
} catch (UserRecoverableAuthException e) {
// Requesting an authorization code will always throw
// UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
// because the user must consent to offline access to their data. After
// consent is granted control is returned to your activity in onActivityResult
// and the second call to GoogleAuthUtil.getToken will succeed.
startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE);
return null;
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}
And in my onActivityResult, I look for the Auth Code
if (requestCode == AUTH_CODE_REQUEST_CODE) {
if (responseCode == RESULT_OK){
Bundle extra = intent.getExtras();
String oneTimeToken = extra.getString("authtoken");
Log.d("LOG", "one time token" + oneTimeToken);
}
}

How to find out technical data about the camera on an Android device?

I want to read out technical data of the installed camera(s) on an Android device (such as: image format, resolution, other technical details), because I eventually want to capture the video stream from the camera and then postprocess it (e.g. compress + stream it). So I'd really like to know what kind of video/picture signal/format the camera returns so that I can work with that.
Is there any way of doing this? I found the getCameraInfo() method, but this merely returns rather not-so-interesting information.
You can find such information with following method.
private static Map<String, String> getFullCameraParameters(Camera cam) {
Map<String, String> result = new HashMap<String, String>(64);
final String TAG = "Home";
try {
Class camClass = cam.getClass();
// Internally, Android goes into native code to retrieve this String
// of values
Method getNativeParams = camClass
.getDeclaredMethod("native_getParameters");
getNativeParams.setAccessible(true);
// Boom. Here's the raw String from the hardware
String rawParamsStr = (String) getNativeParams.invoke(cam);
// But let's do better. Here's what Android uses to parse the
// String into a usable Map -- a simple ';' StringSplitter, followed
// by splitting on '='
//
// Taken from Camera.Parameters unflatten() method
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(
';');
splitter.setString(rawParamsStr);
for (String kv : splitter) {
int pos = kv.indexOf('=');
if (pos == -1) {
continue;
}
String k = kv.substring(0, pos);
String v = kv.substring(pos + 1);
result.put(k, v);
}
// And voila, you have a map of ALL supported parameters
return result;
} catch (NoSuchMethodException ex) {
Log.e(TAG, ex.toString());
} catch (IllegalAccessException ex) {
Log.e(TAG, ex.toString());
} catch (InvocationTargetException ex) {
Log.e(TAG, ex.toString());
}
// If there was any error, just return an empty Map
Log.e(TAG, "Unable to retrieve parameters from Camera.");
return result;
}
To use this method,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
camera = Camera.open();
Map<String, String> info = getFullCameraParameters(camera);
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
camera.release();
}
Take permission in manifest like below.
<uses-permission android:name="android.permission.CAMERA"/>
I got following information in info object. I actually put a debug point for it and then fetch following information. Because i don't know keys. :)
{preferred-preview-size-for-video=176x144, zoom=0, mce=enable, hfr-size-values=, zoom-supported=true, strtextures=OFF, zsl-values=off,on, sharpness=10, hdr-values=, contrast=5, whitebalance=auto, max-sharpness=30, scene-mode=auto, jpeg-quality=85, preview-format-values=yuv420sp,yuv420p,yuv420p, rotation=0, histogram-values=, jpeg-thumbnail-quality=90, preview-format=yuv420sp, overlay-format=265, metering-areas=(-1000,-1000,1000,1000,1000), video-size-values=640x480,640x368,512x288,384x288,352x288,320x240,176x144, skinToneEnhancement=disable, preview-size=640x480, focal-length=1.15, auto-exposure-values=frame-average,center-weighted,spot-metering, video-zoom-support=false, iso=auto, denoise=denoise-off, mce-values=enable,disable, preview-frame-rate-values=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, power-mode-supported=false, max-num-metering-areas=1, semc-metering-mode=center-weighted, preview-frame-rate=30, focus-mode-values=infinity,fixed, jpeg-thumbnail-width=512, scene-mode-values=auto,night,snow,sports, preview-fps-range-values=(1000,15000),(1000,30000), auto-exposure=frame-average, jpeg-thumbnail-size-values=512x288,480x288,432x288,512x384,352x288,0x0, histogram=disable, zoom-ratios=100,102,104,107,109,112,114,117,120,123,125,128,131,135,138,141,144,148,151,155,158,162,166,170,174,178,182,186,190,195,200,204,209,214,219,224,229,235,240,246,251,257,263,270,276,282,289,296,303,310,317,324,332,340,348,356,364,373,381,390,400, camera-mode=0, preview-size-values=640x480,640x368,512x288,384x288,352x288,320x240,176x144, picture-size-values=2048x1536,1920x1080,1632x1224,1280x960,1280x720,640x480,320x240, touch-af-aec=touch-on, preview-fps-range=1000,30000, min-exposure-compensation=-6, antibanding=off, touch-af-aec-values=touch-off,touch-on, max-num-focus-areas=0, vertical-view-angle=42.5, luma-adaptation=3, horizontal-view-angle=54.8, jpeg-thumbnail-height=384, smooth-zoom-supported=true, focus-mode=fixed, max-saturation=10, semc-metering-mode-values=frame-average,center-weighted,spot, max-contrast=10, video-frame-format=yuv420sp, hdr=disable, picture-format-values=jpeg,raw, max-exposure-compensation=6, focus-areas=(-1000,-1000,1000,1000,1000), num-snaps-per-shutter=1, exposure-compensation=0, exposure-compensation-step=0.333333, scene-detect=off, picture-size=640x480, max-zoom=60, saturation=5, whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight, picture-format=jpeg, focus-distances=0.100000,0.150000,Infinity, zsl=off, touchAfAec-dx=100, lensshade-values=disable, touchAfAec-dy=100, iso-values=auto,ISO_HJR,ISO100,ISO200,ISO400,ISO800,ISO1600, lensshade=enable, antibanding-values=off,50hz,60hz,auto}

Unclear instruction in Google Documents List API "Creating or uploading spreadsheets"

I'm trying to create a spreadsheet via my android app. So far I've been only successful in creating an empty text document. Google's Spreadsheet API instructs me to follow Google Documents List API in order to create a spreadsheet document in Google Drive. In Google Documents List API it says:
To create a new, empty spreadsheet, follow the instructions in
Creating a new document or file with metadata only. When doing so, use
a category term of http://schemas.google.com/docs/2007#spreadsheet.
In the link above I've found the next .NET code:
using System;
using Google.GData.Client;
using Google.GData.Documents;
namespace MyDocumentsListIntegration
{
class Program
{
static void Main(string[] args)
{
DocumentsService service = new DocumentsService("MyDocumentsListIntegration-v1");
// TODO: Authorize the service object for a specific user (see Authorizing requests)
// Instantiate a DocumentEntry object to be inserted.
DocumentEntry entry = new DocumentEntry();
// Set the document title
entry.Title.Text = "Legal Contract";
// Add the document category
entry.Categories.Add(DocumentEntry.DOCUMENT_CATEGORY);
// Make a request to the API and create the document.
DocumentEntry newEntry = service.Insert(
DocumentsListQuery.documentsBaseUri, entry);
}
}
}
I've used this code to try and create a spreadsheet, but only the third variant worked (using DocsService, without adding Category and using feedUrl URL object).
Here's part of my working code (upload() is being called when user clicks a button):
private void upload() {
SpreadSheetAsyncTask sprdSheetAsyncTsk = new SpreadSheetAsyncTask();
sprdSheetAsyncTsk.execute();
}
public class SpreadSheetAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
spreadSheetService = new SpreadsheetService("Salary_Calculator");
docService = new DocsService("Salary_Calculator");
try {
spreadSheetService.setUserCredentials(USERNAME, PASSWORD);
docService.setUserCredentials(USERNAME, PASSWORD);
URL feedUrl = new URL(
"https://docs.google.com/feeds/default/private/full/");
URL tmpFeedUrl = new URL(
"https://spreadsheets.google.com/feeds/worksheets/key/private/full");
DocumentEntry entry = new DocumentEntry();
Calendar timeRightNow = GregorianCalendar.getInstance();
entry.setTitle(new PlainTextConstruct(
"Salary Calculator Spreadsheet "
+ timeRightNow.get(Calendar.DAY_OF_MONTH) + "/"
+ (timeRightNow.get(Calendar.MONTH) + 1) + "/"
+ timeRightNow.get(Calendar.YEAR)));
// Category object = new Category("spreadsheet",
// "http://schemas.google.com/docs/2007#spreadsheet");
//
//
// entry.getCategories().add(object);
/*
* TODO TEST AREA
*/
entry = docService.insert(feedUrl, entry);
/*
* TODO TEST AREA
*/
} catch (AuthenticationException e) {
cancel(true);
loginDialog("Wrong username or password");
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ServiceException e) {
cancel(true);
loginDialog("Wrong username or password");
} catch (Exception e) {
loginDialog("Wrong username or password");
}
return null;
}
}
The non working code uses the category object object (as shown in the code comment) above and uses entry = spreadSheetService.insert(feedUrl, entry);
My question is - what did they want me to do when they wrote use a category term of http://schemas.google.com/docs/2007#spreadsheet?

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.

How to get comments of Facebook Notes Items using several Graph API in android app?

I want to show Facebook Page's Notes items with those comments and likes using Graph API.
To do that, I'm using the asyncFacebookRunner in Facebook SDK.
Steps are like this:
call asyncFacebookRunner.request to get Note Item with PageId
mAsyncRunner.request(sAPIString, new NotesRequestListener(), null);
Response has come. ( I can't highlight function call. Sorry for inconvenient to find it.)
public class NotesRequestListener implements com.facebook.android.AsyncFacebookRunner.RequestListener
{
/**
* Called when the request to get notes items has been completed.
* Retrieve and parse and display the JSON stream.
*/
#Override
public void onComplete(String response, Object state) {
// TODO Auto-generated method stub
Log.i("My_TAG", "onComplete with response, state");
try
{
// process the response here: executed in background thread
final JSONObject json = new JSONObject(response);
JSONArray arrNotesItems = json.getJSONArray("data");
int l = (arrNotesItems != null ? arrNotesItems.length() : 0);
// !!!!
// This has another request call
// !!!!
final ArrayList<WordsItem> newItems = WordsItem.getWordsItems(arrNotesItems,getActivity());
WordsActivity.this.runOnUiThread(new Runnable() {
public void run() {
wordsItems.clear();
wordsItems.addAll(newItems);
aa.notifyDataSetChanged();
}
}); // runOnUiThread
} // try
catch (JSONException e)
{
Log.i("My_TAG", "JSON Error in response");
} // catch
} // onComplete
... other override methods ...
} // Request Listener
< Another Class >
public static ArrayList<WordsItem> getWordsItems(JSONArray arrJSON, Activity activity) {
ArrayList<WordsItem> wordsItems = new ArrayList<WordsItem>();
int l = (arrJSON != null ? arrJSON.length() : 0);
try {
WordsItem newItem;
for (int i=0; i<l; i++) {
JSONObject jsonObj = arrJSON.getJSONObject(i);
String sTitle = jsonObj.getString("subject");
String sNoteID = jsonObj.getString("id");
... get another fields here ...
newItem = new WordItem(...);
// !!!!
// This has request call for comments
// !!!!
ArrayList<CommentItem> arrComment = getUserComments(sNoteID);
wordsItems.add(newItem);
}
} catch (Exception e) {
e.printStackTrace();
}
return wordsItems;
} // getWordsItems
call another asyncFacebookRunner.request to get comments of item(with NoteID)
in getUserComments
mAsyncRunner.request(sAPIString, new CommentRequestListener(), null);
Before getting comments(OnComplete in CommentRequestListener has not called), getWordsItems returns item array.
So I can't see the comments.
How can I wait to update UI till getting comments?
(It's so ironic to synchronize asynchronized calls.)
Thanks in advance.
Use facebook object which has non-asynchronous request method.
You need not implement listener method.
So, I suggest below means.
use mAsyncRunner.request for first request call.
use mFacebookRunner.request for second request call.
I hope it may help you:-)
Using FQL - Facebook Query Language you can easily get all this information about any particular note info
, Also to get likes on that and comments over it as like examples given in the links.

Categories

Resources