0

I am trying to implement Salesforce OAuth in Android Application. I have used Salesforce Mobile SDK for implementing it. I have also added 'SalesforceSDK-1.0.1.jar' in my project.

MainActivity.java

package com.android.templateapp;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.salesforce.androidsdk.app.ForceApp;
import com.salesforce.androidsdk.rest.ClientManager;
import com.salesforce.androidsdk.rest.ClientManager.LoginOptions;
import com.salesforce.androidsdk.rest.ClientManager.RestClientCallback;
import com.salesforce.androidsdk.rest.RestClient;


public class MainActivity extends Activity {

private RestClient client;
private ArrayAdapter<String> listAdapter;
private static String TAG = "TemplateApp";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.v(TAG," onCreate of Main Activity");
    // Setup view
    setContentView(R.layout.main);
}

@Override 
public void onResume() {
    Log.v(TAG," ******* default onResume of Main Activity");
        super.onResume();

        findViewById(R.id.root).setVisibility(View.INVISIBLE);
        Log.v(TAG," ******* default onResume - View.INVISIBLE");

        // Login options
        String accountType = ForceApp.APP.getAccountType();

        Log.v(TAG," ******* default onResume - accountType ::"+accountType);

        LoginOptions loginOptions = new LoginOptions(
                "https://login.salesforce.com/", // login host is chosen by user through the server picker 
                ForceApp.APP.getPasscodeHash(),
                getString(R.string.oauth_callback_url),
                getString(R.string.oauth_client_id),
                new String[] {"api"});
        Log.v(TAG," ******* default onResume - loginOptions ::"+loginOptions);


        // Get a rest client
        new ClientManager(this, accountType, loginOptions).getRestClient(this, 
                       new RestClientCallback() {
            @Override
            public void authenticatedRestClient(RestClient client) {

                // Show everything
                findViewById(R.id.root).setVisibility(View.VISIBLE);

                //User is authenticated, insert Application logic here
            }
        });
    }


protected LoginOptions getLoginOptions() {
    Log.v(TAG," getLoginOptions of Main Activity");
    LoginOptions loginOptions = new LoginOptions(
            null, // login host is chosen by user through the server picker 
            ForceApp.APP.getPasscodeHash(),
            getString(R.string.oauth_callback_url),
            getString(R.string.oauth_client_id),
            new String[] {"api"});
    return loginOptions;
}

public void onResume(RestClient client) {
    Log.v(TAG," onResume of Main Activity");
    // Keeping reference to rest client
    this.client = client; 

    // Show everything
    findViewById(R.id.root).setVisibility(View.VISIBLE);
}

/**
 * Called when "Logout" button is clicked. 
 * 
 * @param v
 */
public void onLogoutClick(View v) {
    ForceApp.APP.logout(this);
}

/**
 * Called when "Clear" button is clicked. 
 * 
 * @param v
 */

public void onClearClick(View v) {
    listAdapter.clear();
}   

/**
 * Called when "Fetch Contacts" button is clicked
 * 
 * @param v
 * @throws UnsupportedEncodingException 
 */

public void onFetchContactsClick(View v) throws UnsupportedEncodingException {
    sendRequest("SELECT Name FROM Contact");
}

public void onFetchAccountsClick(View v) throws UnsupportedEncodingException {
    sendRequest("SELECT Name FROM Account");
}   

private void sendRequest(String soql) throws UnsupportedEncodingException {
    RestRequest restRequest = RestRequest.getRequestForQuery(getString(R.string.api_version), soql);

    client.sendAsync(restRequest, new AsyncRequestCallback() {
        @Override
        public void onSuccess(RestRequest request, RestResponse result) {
            try {
                listAdapter.clear();
                JSONArray records = result.asJSONObject().getJSONArray("records");
                for (int i = 0; i < records.length(); i++) {
                    listAdapter.add(records.getJSONObject(i).getString("Name"));
                }                   
            } catch (Exception e) {
                onError(e);
            }
        }

        @Override
        public void onError(Exception exception) {
            Toast.makeText(MainActivity.this,
                           MainActivity.this.getString(ForceApp.APP.getSalesforceR().stringGenericError(), exception.toString()),
                           Toast.LENGTH_LONG).show();
        }
    });
}

}

I am getting following errors in logcat:

12-18 17:47:04.696: E/Trace(1586): error opening trace file: No such file or directory (2)
12-18 17:47:05.256: V/TemplateApp(1586):  onCreate of Main Activity
12-18 17:47:05.526: V/TemplateApp(1586):  ******* default onResume of Main Activity
12-18 17:47:05.526: V/TemplateApp(1586):  ******* default onResume - View.INVISIBLE
12-18 17:47:05.536: D/AndroidRuntime(1586): Shutting down VM
12-18 17:47:05.536: W/dalvikvm(1586): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
12-18 17:47:05.546: E/AndroidRuntime(1586): FATAL EXCEPTION: main
12-18 17:47:05.546: E/AndroidRuntime(1586): java.lang.RuntimeException: Unable to resume activity {com.android.templateapp/com.android.templateapp.MainActivity}: java.lang.NullPointerException
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread.access$600(ActivityThread.java:130)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.os.Looper.loop(Looper.java:137)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread.main(ActivityThread.java:4745)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at java.lang.reflect.Method.invokeNative(Native Method)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at java.lang.reflect.Method.invoke(Method.java:511)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at dalvik.system.NativeStart.main(Native Method)
12-18 17:47:05.546: E/AndroidRuntime(1586): Caused by: java.lang.NullPointerException
12-18 17:47:05.546: E/AndroidRuntime(1586):     at com.salesforce.androidsdk.app.ForceApp.getAccountType(ForceApp.java:175)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at com.android.templateapp.MainActivity.onResume(MainActivity.java:85)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1184)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.Activity.performResume(Activity.java:5082)
12-18 17:47:05.546: E/AndroidRuntime(1586):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
12-18 17:47:05.546: E/AndroidRuntime(1586):     ... 12 more
2
  • thanks @Asmita for question but I want to know how you are importing ForceApp in your application, can you please share some useful regarding it.Thanks in advance. Commented Feb 18, 2014 at 7:17
  • @Asmita . ....please let me know if you found solution . Commented Aug 3, 2017 at 11:07

3 Answers 3

2

I'd imagine that you have not setup an application class that extends ForceApp and registered that in the AndroidManifest.xml file.

Sign up to request clarification or add additional context in comments.

3 Comments

I'm a little uncomfortable extending their ForceApp. Why does it maintain a static reference to itself? Why does it hijack the Main (as they call it) Activity lifecyle? Do I need to delegate their hijacking to fragments? Blagh I guess I'll bite the bullet but it's tough to appreciate SDKs that force their thinking on developers.
How does one go about registering the ForceApp subclass in AndroidManifest.xml? I can't find that info anywhere and I don't see any mention of the ForceApp subclass in the AndroidManifest.xml of the template code. Thanks!
its the standard android application class, so set android:name to the name of the class in the <application> element in the manifest.
0

Refer the following url for authenticating using oAuth

http://wiki.developerforce.com/page/Getting_Started_with_the_Mobile_SDK_for_Android#Authentication

You should give remote access to your salesforce org in order to give access to mobile app. You should specify the remote access consumer key in the application along with oAuth redirect URL & oauth login domain url.

1 Comment

ClientManager has been deprecated and there doesn't seem to be an alternative?
0

I found the same error and superfell's answer helped. If you look at the sample TemplateApp application, TemplateApp.java extends ForceApp. I was able to remove the error by adding it to my Manifest file like :

<application android:icon="@drawable/icon" android:label="@string/app_name" android:name=".TemplateApp">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.