Android Open Source - force_analytics_example Rest Client






From Project

Back to project page force_analytics_example.

License

The source code is released under:

Copyright (c) 2011, salesforce.com, inc. All rights reserved. ======================================== Redistribution and use of this software in source and binary forms, with or without modificatio...

If you think the Android project force_analytics_example listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (c) 2011, salesforce.com, inc.
 * All rights reserved.//  ww w  . j av  a  2  s. c o m
 * Redistribution and use of this software in source and binary forms, with or
 * without modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * - Neither the name of salesforce.com, inc. nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission of salesforce.com, inc.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package com.salesforce.androidsdk.rest;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.BasicNetwork;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.HttpStack;
import com.android.volley.toolbox.NoCache;
import com.google.common.collect.Maps;
import com.salesforce.androidsdk.auth.HttpAccess;
import com.salesforce.androidsdk.auth.HttpAccess.Execution;
import com.salesforce.androidsdk.rest.RestRequest.RestMethod;

/**
 * RestClient allows you to send authenticated HTTP requests to a force.com server.
 */
public class RestClient {

  private ClientInfo clientInfo;
  private RequestQueue requestQueue;
  private SalesforceHttpStack httpStack;
  
  /** 
   * AuthTokenProvider interface.
   * RestClient will call its authTokenProvider to refresh its authToken once it has expired. 
   */
  public interface AuthTokenProvider {
    String getNewAuthToken();
    String getRefreshToken();
    long getLastRefreshTime();
  }
  
  /**
   * AsyncRequestCallback interface.
   * Interface through which the result of an asynchronous request is handled.
   */
  public interface AsyncRequestCallback {
    void onSuccess(RestRequest request, RestResponse response);
    void onError(Exception exception);
  }
  
    /**
     * Constructs a RestClient with the given clientInfo, authToken, httpAccessor and authTokenProvider.
     * When it gets a 401 (not authorized) response from the server:
     * <ul>
     * <li> If authTokenProvider is not null, it will ask the authTokenProvider for a new access token and retry the request a second time.</li>
     * <li> Otherwise it will return the 401 response.</li>
     * </ul>
   * @param clientInfo
     * @param authToken
     * @param httpAccessor
     * @param authTokenProvider
   */
  public RestClient(ClientInfo clientInfo, String authToken, HttpAccess httpAccessor, AuthTokenProvider authTokenProvider) {
    this(clientInfo, new SalesforceHttpStack(authToken, httpAccessor, authTokenProvider));
  }

  public RestClient(ClientInfo clientInfo, SalesforceHttpStack httpStack) {
    this.clientInfo = clientInfo;
    this.httpStack = httpStack;
    this.requestQueue = new RequestQueue(new NoCache(), new BasicNetwork(httpStack));
    this.requestQueue.start();
  }
  
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("RestClient: {\n")
      .append(getClientInfo())
      // Un-comment if you must: tokens should not be printed to the log
      // .append("   authToken: ").append(getAuthToken()).append("\n")
      // .append("   refreshToken: ").append(getRefreshToken()).append("\n")
      .append("   timeSinceLastRefresh: ").append(httpStack.getElapsedTimeSinceLastRefresh()).append("\n")
      .append("}\n");
    return sb.toString();
  }
  
  /**
   * @return The authToken for this RestClient.
   */
  public synchronized String getAuthToken() {
    return httpStack.getAuthToken();
  }
  
  /**
   * @return The refresh token, if available.
   */
  public String getRefreshToken() {
    return httpStack.getRefreshToken();
  }
  
  /**
   * @return The client info.
   */
  public ClientInfo getClientInfo() {
    return clientInfo;
  }
  
  /**
   * @return underlying RequestQueue (using when calling sendAsync)
   */
  public RequestQueue getRequestQueue() {
    return requestQueue;
  }
  
  /**
   * Send the given restRequest and process the result asynchronously with the given callback.
   * Note: Intended to be used by code on the UI thread.
   * @param restRequest
   * @param callback
   * @return volley.Request object wrapped around the restRequest (to allow cancellation etc)
   */
  public Request<?> sendAsync(RestRequest restRequest, AsyncRequestCallback callback) {
    WrappedRestRequest wrappedRestRequest = new WrappedRestRequest(clientInfo, restRequest, callback);
    return requestQueue.add(wrappedRestRequest);
  }

  /**
   * Send the given restRequest synchronously and return a RestResponse
   * Note: Cannot be used by code on the UI thread (use sendAsync instead).
   * @param restRequest
   * @return
   * @throws IOException 
   */
  public RestResponse sendSync(RestRequest restRequest) throws IOException {
    return sendSync(restRequest.getMethod(), restRequest.getPath(), restRequest.getRequestEntity(), restRequest.getAdditionalHttpHeaders());
  }

  /**
   * Send an arbitrary HTTP request synchronously, using the given method, path and httpEntity.
   * Note: Cannot be used by code on the UI thread (use sendAsync instead).
   * 
   * @param method        the HTTP method for the request (GET/POST/DELETE etc)
   * @param path          the URI path, this will automatically be resolved against the users current instance host.
   * @param httpEntity      the request body if there is one, can be null.
   * @param additionalHttpHeaders additional HTTP headers to add the generated HTTP request, can be null.
   * @return             a RestResponse instance that has information about the HTTP response returned by the server. 
   */
  public RestResponse sendSync(RestMethod method, String path, HttpEntity httpEntity) throws IOException {
    return sendSync(method, path, httpEntity, null);
  }

  /**
   * Send an arbitrary HTTP request synchronously, using the given method, path, httpEntity and additionalHttpHeaders.
   * Note: Cannot be used by code on the UI thread (use sendAsync instead).
   * 
   * @param method        the HTTP method for the request (GET/POST/DELETE etc)
   * @param path          the URI path, this will automatically be resolved against the users current instance host.
   * @param httpEntity      the request body if there is one, can be null.
   * @param additionalHttpHeaders additional HTTP headers to add the generated HTTP request, can be null.
   * @return             a RestResponse instance that has information about the HTTP response returned by the server. 
   * 
   * @throws IOException
   */
  public RestResponse sendSync(RestMethod method, String path, HttpEntity httpEntity, Map<String, String> additionalHttpHeaders) throws IOException {
    return new RestResponse(httpStack.performRequest(method.asVolleyMethod(), clientInfo.resolveUrl(path), httpEntity, additionalHttpHeaders, true));
  }
  
  
  /**
   * Only used in tests
   * @param httpAccessor
   */
  public void setHttpAccessor(HttpAccess httpAccessor) {
    this.httpStack.setHttpAccessor(httpAccessor);
  }
  
  /**
   * All immutable information for an authenticated client (e.g. username, org ID, etc.).
   */
  public static class ClientInfo {

    public final String clientId;
    public final URI instanceUrl;
    public final URI loginUrl;
    public final URI identityUrl;
    public final String accountName;
    public final String username;
    public final String userId;
    public final String orgId;
    public final String communityId;
    public final String communityUrl;

    /**
     * Parameterized constructor.
     *
     * @param clientId Client ID.
     * @param instanceUrl Instance URL.
     * @param loginUrl Login URL.
     * @param identityUrl Identity URL.
     * @param accountName Account name.
     * @param username User name.
     * @param userId User ID.
     * @param orgId Org ID.
     * @param communityId Community ID.
     * @param communityUrl Community URL.
     */
    public ClientInfo(String clientId, URI instanceUrl, URI loginUrl,
        URI identityUrl, String accountName, String username,
        String userId, String orgId, String communityId, String communityUrl) {
      this.clientId = clientId;
      this.instanceUrl = instanceUrl;
      this.loginUrl = loginUrl;
      this.identityUrl = identityUrl;
      this.accountName = accountName;
      this.username = username;  
      this.userId = userId;
      this.orgId = orgId;
      this.communityId = communityId;
      this.communityUrl = communityUrl;
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append("  ClientInfo: {\n")
        .append("     loginUrl: ").append(loginUrl.toString()).append("\n")
        .append("     identityUrl: ").append(identityUrl.toString()).append("\n")
        .append("     instanceUrl: ").append(instanceUrl.toString()).append("\n")
        .append("     accountName: ").append(accountName).append("\n")
        .append("     username: ").append(username).append("\n")
        .append("     userId: ").append(userId).append("\n")
        .append("     orgId: ").append(orgId).append("\n")
        .append("     communityId: ").append(communityId).append("\n")
        .append("     communityUrl: ").append(communityUrl).append("\n")
        .append("  }\n");
      return sb.toString();
    }

    /**
     * Returns a string representation of the instance URL. If this is a
     * community user, the community URL will be returned. If not, the
     * instance URL will be returned.
     *
     * @return Instance URL.
     */
    public String getInstanceUrlAsString() {
      if (communityUrl != null && !"".equals(communityUrl.trim())) {
        return communityUrl;
      }
      return instanceUrl.toString();
    }

    /**
     * Returns a URI representation of the instance URL. If this is a
     * community user, the community URL will be returned. If not, the
     * instance URL will be returned.
     *
     * @return Instance URL.
     */
    public URI getInstanceUrl() {
      if (communityUrl != null && !"".equals(communityUrl.trim())) {
        URI uri = null;
        try {
          uri = new URI(communityUrl);
        } catch (URISyntaxException e) {
          Log.e("ClientInfo: getCommunityInstanceUrl",
              "URISyntaxException thrown on URL: " + communityUrl);
        }
        return uri;
      }
      return instanceUrl;
    }

    /**
     * Resolves the given path against the community URL or the instance
     * URL, depending on whether the user is a community user or not.
     *
     * @param path Path.
     * @return Resolved URL.
     */
    public URI resolveUrl(String path) {
      final StringBuilder commInstanceUrl = new StringBuilder();
      if (communityUrl != null && !"".equals(communityUrl.trim())) {
        commInstanceUrl.append(communityUrl);
      } else {
        commInstanceUrl.append(instanceUrl.toString());
      }
      if (!commInstanceUrl.toString().endsWith("/")) {
        commInstanceUrl.append("/");
      }
      if (path.startsWith("/")) {
        path = path.substring(1);
      }
      commInstanceUrl.append(path);
      URI uri = null;
      try {
        uri = new URI(commInstanceUrl.toString());
      } catch (URISyntaxException e) {
        Log.e("ClientInfo: resolveUrl",
            "URISyntaxException thrown on URL: " + commInstanceUrl.toString());
      }
      return uri;
    }
  }

  /**
   * HttpStack for talking to Salesforce (sets oauth header and does oauth refresh when needed)
   */
  public static class SalesforceHttpStack implements HttpStack {

    private final AuthTokenProvider authTokenProvider;
    private HttpAccess httpAccessor;
    private String authToken;
    
      /**
       * Constructs a SalesforceHttpStack with the given clientInfo, authToken, httpAccessor and authTokenProvider.
       * When it gets a 401 (not authorized) response from the server:
       * <ul>
       * <li> If authTokenProvider is not null, it will ask the authTokenProvider for a new access token and retry the request a second time.</li>
       * <li> Otherwise it will return the 401 response.</li>
       * </ul>
       * @param authToken
       * @param httpAccessor
       * @param authTokenProvider
     */
    public SalesforceHttpStack(String authToken, HttpAccess httpAccessor, AuthTokenProvider authTokenProvider) {
      this.authToken = authToken;
      this.httpAccessor = httpAccessor;
      this.authTokenProvider = authTokenProvider;
    }
    
    @Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
        throws IOException, AuthFailureError {

      int method = request.getMethod();
      URI url = URI.create(request.getUrl());
      HttpEntity requestEntity = null;
          
      if (request instanceof WrappedRestRequest) {
        RestRequest restRequest = ((WrappedRestRequest) request).getRestRequest();
        
        // To avoid httpEntity -> bytes -> httpEntity conversion
        requestEntity = restRequest.getRequestEntity();
        
        // Combine headers
        if (restRequest.getAdditionalHttpHeaders() != null) {
          if (additionalHeaders == null) {
            additionalHeaders = restRequest.getAdditionalHttpHeaders(); 
          }
          else {
            additionalHeaders = Maps.newHashMap(additionalHeaders);
            additionalHeaders.putAll(restRequest.getAdditionalHttpHeaders());
            
          }
        }
      }
      else {
        if (request.getBody() != null) {
          requestEntity = new ByteArrayEntity(request.getBody());
        }
      }
      
      return performRequest(method, url, requestEntity, additionalHeaders, true);
    }
    
    /**
     * @return The authToken for this RestClient.
     */
    public synchronized String getAuthToken() {
      return authToken;
    }
    
    /**
     * Change authToken for this RestClient
     * @param newAuthToken
     */
    private synchronized void setAuthToken(String newAuthToken) {
      authToken = newAuthToken;
    }

    /**
     * @return The refresh token, if available.
     */
    public String getRefreshToken() {
      return (authTokenProvider != null ? authTokenProvider.getRefreshToken() : null);
    }
    
    /**
     * @return Elapsed time (ms) since the last refresh.
     */
    public long getElapsedTimeSinceLastRefresh() {
      long lastRefreshTime = (authTokenProvider != null ? authTokenProvider.getLastRefreshTime() : -1);
      if (lastRefreshTime < 0) {
        return -1;
      }
      else {
        return System.currentTimeMillis() - lastRefreshTime;
      }
    }

    /**
     * Only used in tests
     * @param httpAccessor
     */
    public void setHttpAccessor(HttpAccess httpAccessor) {
      this.httpAccessor = httpAccessor; 
    }

    /**
     * @param method
     * @param url
     * @param httpEntity
     * @param additionalHttpHeaders
     * @param retryInvalidToken
     * @return
     * @throws IOException
     */
    public HttpResponse performRequest(int method, URI url, HttpEntity httpEntity, Map<String, String> additionalHttpHeaders, boolean retryInvalidToken) throws IOException {
      Execution exec = null;

      // Prepare headers
      Map<String, String> headers = new HashMap<String, String>();
      if (additionalHttpHeaders != null) {
        headers.putAll(additionalHttpHeaders);
      }
      if (getAuthToken() != null) {
        headers.put("Authorization", "Bearer " + authToken);
      }

      // Do the actual call
      switch(method) {
      case Request.Method.DELETE:
        exec = httpAccessor.doDelete(headers, url); break;
      case Request.Method.GET:
        exec = httpAccessor.doGet(headers, url); break;
      case RestMethod.MethodHEAD:
        exec = httpAccessor.doHead(headers, url); break;
      case RestMethod.MethodPATCH:
        exec = httpAccessor.doPatch(headers, url, httpEntity); break;
      case Request.Method.POST:
        exec = httpAccessor.doPost(headers, url, httpEntity); break;
      case Request.Method.PUT:
        exec = httpAccessor.doPut(headers, url, httpEntity); break;
      }

      HttpResponse response = exec.response;
      int statusCode = response.getStatusLine().getStatusCode();

      // 401 bad access token *
      if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
        // If we haven't retried already and we have an accessTokenProvider
        // Then let's try to get a new authToken
        if (retryInvalidToken && authTokenProvider != null) {
          // remember to consume this response so the connection can get re-used
          HttpEntity entity = response.getEntity();
          if (entity != null && entity.isStreaming()) {
            InputStream instream = entity.getContent();
            if (instream != null) {
              instream.close();
            }
          }
          String newAuthToken = authTokenProvider.getNewAuthToken();
          if (newAuthToken != null) {
            setAuthToken(newAuthToken);
            // Retry with the new authToken
            return performRequest(method, url, httpEntity, additionalHttpHeaders, false);
          }
        }
      }
      
      // Done
      return response;
    }
  }
  
  /**
   * A RestRequest wrapped in a Request<?>
   */
  public static class WrappedRestRequest extends Request<RestResponse> {

    private RestRequest restRequest;
    private AsyncRequestCallback callback;

    /**
     * Constructor
     * @param restRequest
     * @param callback
     */
    public WrappedRestRequest(ClientInfo clientInfo, RestRequest restRequest, final AsyncRequestCallback callback) {
      super(restRequest.getMethod().asVolleyMethod(), 
          clientInfo.resolveUrl(restRequest.getPath()).toString(), 
          new Response.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError error) {
            callback.onError(error);
          }
        });
      this.restRequest = restRequest;
      this.callback = callback;
    }

    public RestRequest getRestRequest() {
      return restRequest;
    }

    public HttpEntity getRequestEntity() {
      return restRequest.getRequestEntity();
    }
    
    @Override
    public byte[] getBody() throws AuthFailureError {
      try {
        HttpEntity requestEntity = restRequest.getRequestEntity();
        return requestEntity == null ? null : EntityUtils.toByteArray(requestEntity);
      }
      catch (IOException e) {
        Log.e("WrappedRestRequest.getBody", "Could not read request entity", e);
        return null;
      }
    }

    @Override
      public String getBodyContentType() {
      HttpEntity requestEntity = restRequest.getRequestEntity();
      Header contentType = requestEntity == null ? null : requestEntity.getContentType();
      return (contentType == null ? "application/x-www-form-urlencoded" : contentType.getValue()) + "; charset=" + HTTP.UTF_8;
      }    
    
    @Override
    protected void deliverResponse(RestResponse restResponse) {
      callback.onSuccess(restRequest, restResponse);
    }

    @Override
    protected Response<RestResponse> parseNetworkResponse(
        NetworkResponse networkResponse) {
            return Response.success(new RestResponse(networkResponse),
                    HttpHeaderParser.parseCacheHeaders(networkResponse));
    }
    
  }
}




Java Source Code List

com.salesforce.androidsdk.accounts.UserAccountManagerWithSmartStore.java
com.salesforce.androidsdk.accounts.UserAccountManager.java
com.salesforce.androidsdk.accounts.UserAccount.java
com.salesforce.androidsdk.app.SalesforceSDKManager.java
com.salesforce.androidsdk.app.UUIDManager.java
com.salesforce.androidsdk.app.UpgradeManager.java
com.salesforce.androidsdk.auth.AccountWatcher.java
com.salesforce.androidsdk.auth.AuthenticatorService.java
com.salesforce.androidsdk.auth.HttpAccess.java
com.salesforce.androidsdk.auth.LoginServerManager.java
com.salesforce.androidsdk.auth.OAuth2.java
com.salesforce.androidsdk.phonegap.ForcePlugin.java
com.salesforce.androidsdk.phonegap.JavaScriptPluginVersion.java
com.salesforce.androidsdk.phonegap.SDKInfoPlugin.java
com.salesforce.androidsdk.phonegap.SFAccountManagerPlugin.java
com.salesforce.androidsdk.phonegap.SalesforceOAuthPlugin.java
com.salesforce.androidsdk.phonegap.TestRunnerPlugin.java
com.salesforce.androidsdk.push.PushBroadcastReceiver.java
com.salesforce.androidsdk.push.PushMessaging.java
com.salesforce.androidsdk.push.PushNotificationInterface.java
com.salesforce.androidsdk.push.PushService.java
com.salesforce.androidsdk.rest.AdminPrefsManager.java
com.salesforce.androidsdk.rest.ApiVersionStrings.java
com.salesforce.androidsdk.rest.BootConfig.java
com.salesforce.androidsdk.rest.ClientManager.java
com.salesforce.androidsdk.rest.RestClient.java
com.salesforce.androidsdk.rest.RestRequest.java
com.salesforce.androidsdk.rest.RestResponse.java
com.salesforce.androidsdk.rest.files.ApiRequests.java
com.salesforce.androidsdk.rest.files.ConnectUriBuilder.java
com.salesforce.androidsdk.rest.files.FileRequests.java
com.salesforce.androidsdk.rest.files.RenditionType.java
com.salesforce.androidsdk.security.Encryptor.java
com.salesforce.androidsdk.security.PRNGFixes.java
com.salesforce.androidsdk.security.PasscodeManager.java
com.salesforce.androidsdk.smartstore.app.SalesforceSDKManagerWithSmartStore.java
com.salesforce.androidsdk.smartstore.app.UpgradeManagerWithSmartStore.java
com.salesforce.androidsdk.smartstore.phonegap.SmartStorePlugin.java
com.salesforce.androidsdk.smartstore.phonegap.StoreCursor.java
com.salesforce.androidsdk.smartstore.store.DBHelper.java
com.salesforce.androidsdk.smartstore.store.DBOpenHelper.java
com.salesforce.androidsdk.smartstore.store.IndexSpec.java
com.salesforce.androidsdk.smartstore.store.QuerySpec.java
com.salesforce.androidsdk.smartstore.store.SmartSqlHelper.java
com.salesforce.androidsdk.smartstore.store.SmartStore.java
com.salesforce.androidsdk.ui.AccountSwitcherActivity.java
com.salesforce.androidsdk.ui.CustomServerUrlEditor.java
com.salesforce.androidsdk.ui.LoginActivity.java
com.salesforce.androidsdk.ui.ManageSpaceActivity.java
com.salesforce.androidsdk.ui.OAuthWebviewHelper.java
com.salesforce.androidsdk.ui.PasscodeActivity.java
com.salesforce.androidsdk.ui.SalesforceAccountRadioButton.java
com.salesforce.androidsdk.ui.SalesforceR.java
com.salesforce.androidsdk.ui.SalesforceServerRadioButton.java
com.salesforce.androidsdk.ui.ServerPickerActivity.java
com.salesforce.androidsdk.ui.sfhybrid.SalesforceDroidGapActivity.java
com.salesforce.androidsdk.ui.sfhybrid.SalesforceGapViewClient.java
com.salesforce.androidsdk.ui.sfnative.SalesforceActivity.java
com.salesforce.androidsdk.ui.sfnative.SalesforceExpandableListActivity.java
com.salesforce.androidsdk.ui.sfnative.SalesforceListActivity.java
com.salesforce.androidsdk.util.EventsListenerQueue.java
com.salesforce.androidsdk.util.EventsObservable.java
com.salesforce.androidsdk.util.EventsObserver.java
com.salesforce.androidsdk.util.ForceAppInstrumentationTestCase.java
com.salesforce.androidsdk.util.HybridInstrumentationTestCase.java
com.salesforce.androidsdk.util.JSTestCase.java
com.salesforce.androidsdk.util.JUnitReportTestRunner.java
com.salesforce.androidsdk.util.LogUtil.java
com.salesforce.androidsdk.util.NativeInstrumentationTestCase.java
com.salesforce.androidsdk.util.TimeLimitedTestRunner.java
com.salesforce.androidsdk.util.TokenRevocationReceiver.java
com.salesforce.androidsdk.util.UriFragmentParser.java
com.salesforce.androidsdk.util.UserSwitchReceiver.java
com.salesforce.samples.accounteditor.AccountEditorApp.java
com.salesforce.samples.accounteditor.KeyImpl.java
com.salesforce.samples.analyticsapp.AnalyticsApp.java
com.salesforce.samples.analyticsapp.GraphActivity.java
com.salesforce.samples.analyticsapp.KeyImpl.java
com.salesforce.samples.analyticsapp.MainActivity.java
com.salesforce.samples.analyticsapp.PieChart.java
com.salesforce.samples.contactexplorer.ContactExplorerApp.java
com.salesforce.samples.contactexplorer.KeyImpl.java
com.salesforce.samples.hybridfileexplorer.HybridFileExplorerApp.java
com.salesforce.samples.hybridfileexplorer.KeyImpl.java
com.salesforce.samples.smartstoreexplorer.KeyImpl.java
com.salesforce.samples.smartstoreexplorer.SmartStoreExplorerApp.java
com.salesforce.samples.vfconnector.KeyImpl.java
com.salesforce.samples.vfconnector.VFConnectorApp.java