I want to use the SafetyNet Attestation API (mind that this documentation seems to be outdated since the methods it uses are deprecated). Using the latest version of Play Services (11.0.1) I came up with the following code:
SecureRandom secureRandom = new SecureRandom();
byte[] nonce = new byte[16];
secureRandom.nextBytes(nonce); // just some random bytes for testing
SafetyNet.getClient(this)
.attest(nonce, API_KEY)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
SafetyNetApi.AttestationResponse result = task.getResult();
String jws = result.getJwsResult();
Log.d(TAG, "JWS: " + jws);
} else {
Exception e = task.getException();
if (e instanceof ApiException) {
Log.e(TAG, "Attestation failure: " + ((ApiException) e).getStatusMessage() + ", code: " + ((ApiException) e).getStatusCode(), e);
} else {
Log.e(TAG, "Attestation failure: " + e, e);
}
}
});
where API_KEY is the API key from the Google Developer Console. This code is called in an Activity's onCreate(...). Whatever I tried, it results in failure and the e is an instance of ApiException, but it does not provide any useful information about what went wrong since the status message is null and the status code is 8, which - according to the documentation - is an "internal error". I tried to call this with a 5 second delay but no success. The test device has API 24 and Google Play services 11.0.55.
Anyone has any idea what goes wrong and what's the solution for this?
Edit: the old SafetyNet.SafetyNetApi.attest(googleApiClient, nonce) way seems to work fine but it's deprecated so I don't want to use it.
Based from this thread, if you get error code 8 (INTERNAL_ERROR), please double check your app registration in dev console. Note that every registered Android client is uniquely identified by the (package name, Android Signing Certificate SHA-1) pair. If you have multiple package names / signing certificate for your debug and production environments, make sure to register every pair of them.
To verify:
Open the Credentials page and select your project
Make sure every pair has an Android typed OAuth 2.0 client IDs. To create a new OAuth 2.0 client ID for your Android client, select New Credentials->OAuth2 Client ID from the dropdown, select Android and input your Package name / Signing-certificate fingerprint there.
If it doesn't work, I recommend you to contact the Google Play team for help. You can reach them from this link here: https://support.google.com/googleplay#topic=3364260&contact=1.
Ensure that you are using correct WEB API KEY in your following code:
SafetyNet.getClient(this)
.attest(nonce, WEB_API_KEY)......
See following image to find WEB API KEY:
FCM Console
// Build.gradle
implementation 'com.google.firebase:firebase-core:17.2.1'
implementation 'com.google.firebase:firebase-messaging:20.1.0'
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.google.android.gms:play-services-safetynet:17.0.0'
implementation 'com.google.android.gms:play-services-tasks:17.0.0'
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.safetynet.SafetyNetClient;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;
import com.google.android.gms.safetynet.SafetyNetClient;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.safetynet.SafetyNetApi.AttestationResponse;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Random;
#Override
public void onConnected(Bundle bundle) {
Log.d("My Project Name:", "Google play services connected");
runSafetyNetTest(mContext);
}
private byte[] getRequestNonce(String data) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] bytes = new byte[24];
mRandom.nextBytes(bytes);
try {
byteStream.write(bytes);
byteStream.write(data.getBytes());
} catch (IOException e) {
return null;
}
public void runSafetyNetTest(Context context) {
String nonceData = "734K78J56KJ745JH78LKJ9CSOC3477tj35f345j7" + System.currentTimeMillis();
byte[] nonce = getRequestNonce(nonceData);
SafetyNetClient client = SafetyNet.getClient(context);
Task<SafetyNetApi.AttestationResponse> task = client.attest(nonce, this.googleDeviceVerificationApiKey);
task.addOnSuccessListener( mSuccessListener).addOnFailureListener(mFailureListener);
}
private OnSuccessListener<SafetyNetApi.AttestationResponse> mSuccessListener =
new OnSuccessListener<SafetyNetApi.AttestationResponse>() {
#Override
public void onSuccess(SafetyNetApi.AttestationResponse attestationResponse) {
mResult = attestationResponse.getJwsResult();
// writeLog( "Success! SafetyNet result:\n" + mResult + "\n");
final String jwsResult = mResult;
final SafetyNetResponse response = parseJsonWebSignature(jwsResult);
lastResponse = response;
//only need to validate the response if it says we pass
if (!response.isCtsProfileMatch() || !response.isBasicIntegrity()) {
// This is Result........
callback.success(response.isCtsProfileMatch(), response.isBasicIntegrity());
return;
} else {
//validate payload of the response
if(true/*validateSafetyNetResponsePayload(response)*/) {
if (googleDeviceVerificationApiKey != "")
{
//if the api key is set, run the AndroidDeviceVerifier
AndroidDeviceVerifier androidDeviceVerifier = new AndroidDeviceVerifier(googleDeviceVerificationApiKey, jwsResult);
androidDeviceVerifier.verify(new AndroidDeviceVerifier.AndroidDeviceVerifierCallback() {
#Override
public void error(String errorMsg) {
callback.error(RESPONSE_ERROR_VALIDATING_SIGNATURE, "Response signature validation error: " + errorMsg);
}
#Override
public void success(boolean isValidSignature) {
if (isValidSignature) {
callback.success(response.isCtsProfileMatch(), response.isBasicIntegrity());
} else {
callback.error(RESPONSE_FAILED_SIGNATURE_VALIDATION, "Response signature invalid");
}
}
});
} else {
Log.w(TAG, "No google Device Verification ApiKey defined");
callback.error(RESPONSE_FAILED_SIGNATURE_VALIDATION_NO_API_KEY, "No Google Device Verification ApiKey defined. Marking as failed. SafetyNet CtsProfileMatch: " + response.isCtsProfileMatch());
}
} else {
callback.error(RESPONSE_VALIDATION_FAILED, "Response payload validation failed");
}
}
}
};
private OnFailureListener mFailureListener = new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// An error occurred while communicating with the service.
mResult = null;
if (e instanceof ApiException) {
// An error with the Google Play Services API contains some additional details.
ApiException apiException = (ApiException) e;
writeLog( "Error: " +
CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " +
apiException.getStatusMessage());
} else {
// A different, unknown type of error occurred.
writeLog( "ERROR! " + e.getMessage());
}
}
};
Related
I am trying to build an android app that'll allow me to upload files to Google Drive upon requirement of the user. But, I can't find a single working example anywhere. There are half baked snippets scattered here and there. Some of them are able to connect through OAuth, others are able to create an empty file or folder, but nowhere I can find an app that saves the tokens, and uploads the files seamlessly. I am just clueless as to how to implement the functionality as no books or videos are available, google's own samples don't work for me. I'm struggling to make the code work. Please help someone. Thanks.
I always use the class below to create a Google drive service.
First you need to have these dependencies on your pom file :
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-drive</artifactId>
<version>v2-rev282-1.23.0</version>
</dependency>
Then use this class to create instance of the drive api client :
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
/**
*
* #author jalal-sordo
*/
public class GoogleDriveServiceFactory {
private String applicationName;
private JsonFactory jsonFactory;
private HttpTransport googleDriveHttpTransport;
private List<String> googleDriveApiScopes;
private String googleDriveClientSecretFilePath;
private FileDataStoreFactory credentialsStoreFolder;
public GoogleDriveServiceFactory(ApplicationParameters params) {
try {
this.googleDriveClientSecretFilePath = params.getGoogleDriveClientSecretFilePath();
// = new FileInputStream(googleDriveClientSecretFilePath);
applicationName = "someApplicationName";
jsonFactory = JacksonFactory.getDefaultInstance();
googleDriveApiScopes = Arrays.asList(DriveScopes.DRIVE);
googleDriveHttpTransport = GoogleNetHttpTransport.newTrustedTransport();
java.io.File googleDriveCredentialsStore = new java.io.File(params.getGoogleDriveCredentialsFolderPath());
credentialsStoreFolder = new FileDataStoreFactory(googleDriveCredentialsStore);
} catch (IOException | GeneralSecurityException t) {
System.err.println(t.getMessage());
System.exit(1);
}
}
public Credential authorize() throws IOException {
InputStreamReader streamReader = new FileReader(new java.io.File(googleDriveClientSecretFilePath));
GoogleClientSecrets clientSecrets
= GoogleClientSecrets.load(jsonFactory, streamReader);
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow
= new GoogleAuthorizationCodeFlow.Builder(
googleDriveHttpTransport, jsonFactory, clientSecrets, googleDriveApiScopes)
.setDataStoreFactory(credentialsStoreFolder)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(
flow, new LocalServerReceiver()).authorize("user");
return credential;
}
public Drive getDriveService() throws IOException {
Credential credential = authorize();
return new Drive.Builder(
googleDriveHttpTransport, jsonFactory, credential)
.setApplicationName(applicationName)
.build();
}
}
You will also need this class to provide parameters to the class above :
/**
*
* #author jalal-sordo
*/
public class ApplicationParameters {
private String googleDriveCredentialsFolderPath;
private String googleDriveClientSecretFilePath;
public String getGoogleDriveCredentialsFolderPath() {
return googleDriveCredentialsFolderPath;
}
public void setGoogleDriveCredentialsFolderPath(String googleDriveCredentialsFolderPath) {
this.googleDriveCredentialsFolderPath = googleDriveCredentialsFolderPath;
}
public String getGoogleDriveClientSecretFilePath() {
return googleDriveClientSecretFilePath;
}
public void setGoogleDriveClientSecretFilePath(String googleDriveClientSecretFilePath) {
this.googleDriveClientSecretFilePath = googleDriveClientSecretFilePath;
}
#Override
public String toString() {
return "ApplicationParameters{"
+ "\ngoogleDriveCredentialsFolderPath = " + googleDriveCredentialsFolderPath
+ "\ngoogleDriveClientSecretFilePath = " + googleDriveClientSecretFilePath
+ "\n}";
}
}
And this is how you can create an instance of the GoogleDriveServiceFactory and perform a file upload :
ApplicationParameters params = new ApplicationParameters();
//this is where you specify where you want the credentials to be stored
//after a successful autherization is made from the browser (this code will
//open the authorization consent page on your default browser).
params.setGoogleDriveCredentialsFolderPath("/path/to/credentials/folder");
//this is the path to your client_id that you downloaded from google cloud
//console credentials page.
params.setGoogleDriveClientSecretFilePath("/path/to/client_id.json");
GoogleDriveServiceFactory driveFactory = new GoogleDriveServiceFactory (params);
File fileMetadata = new File();
fileMetadata.setName("photo.jpg");
java.io.File filePath = new java.io.File("files/photo.jpg");
FileContent mediaContent = new FileContent("image/jpeg", filePath);
File file = driveFactory.getDriveService.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());
I am simply following the tutorial outlined in: https://cloud.google.com/solutions/mobile/firebase-app-engine-android-studio, section Add the backend module.
The Servlet code I have is:
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
static Logger Log = Logger.getLogger("com.example.username.myapplication.backend.MyServlet");
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
Log.info("Got cron message, constructing email.");
//Create a new Firebase instance and subscribe on child events.
Firebase firebase = new Firebase("[firebase-DB]");
firebase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Build the email message contents using every field from Firebase.
final StringBuilder newItemMessage = new StringBuilder();
newItemMessage.append("Hello main user");
//Now Send the email
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try {
Message msg = new MimeMessage(session);
//Make sure you substitute your project-id in the email From field
msg.setFrom(new InternetAddress("anything#firebasebackendserver.appspotmail.com",
"Todo Nagger"));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress("myEmail#gmail.com", "Recipient"));
msg.setSubject("Good Morning!");
msg.setText(newItemMessage.toString());
Transport.send(msg);
} catch (MessagingException | UnsupportedEncodingException e) {
Log.warning(e.getMessage());
}
}
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
And the cron.xml file as:
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/hello</url>
<description>Send me an email of outstanding items in the morning</description>
<schedule>every 1 minutes</schedule>
</cron>
</cronentries>
After completing an in Firebase, the AppEngine dashboard does register that a request has occurred, however, the email is never sent, all I see in the logs is the error:
Caused by: com.google.apphosting.api.ApiProxy$FeatureNotEnabledException: The Socket API will be enabled for this application once billing has been enabled in the admin console.
Even though I have already enabled billing for this app.
Is there some sort of grace period after billing is enabled before you can actually begin to use it...?
What is wrong with the code layout?
I suspect you're sending from a disallowed sender. Here's an excerpt from the docs:
For security purposes, the sender address of a message must be one of the following:
The Gmail or Google Apps Account of the user who is currently signed in
Any email address of the form anything#appname.appspotmail.com or anything#appalias.appspotmail.com
Any email address listed in the Cloud Platform Console under Email API Authorized Senders
If this is the case, you will see an error in the logs.
I want to use Azure to push notification in China. And I read the Document that it seems only can use Baidu's Platform if you want to push to Android device.
I follow the official tutorial but there is a missing method in it.
Error:(48, 24) error: cannot find symbol method registerBaidu(String,String)
here is my code:
private void registerWithNotificationHubs() {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
hub.registerBaidu(mUserId, mChannelId);
Log.i(TAG, "Registered with Notification Hub - '"
+ ConfigurationSettings.NotificationHubName + "'"
+ " with UserId - '"
+ mUserId + "' and Channel Id - '"
+ mChannelId + "'");
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return null;
}
}.execute(null, null, null);
}
And the hub belongs to NotificationHub.
And here is my import:
package com.example.henryhkpush;
import java.util.List;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.baidu.frontia.api.FrontiaPushMessageReceiver;
import com.microsoft.windowsazure.messaging.NotificationHub;
And i go to the NotificationHub.jar folder,there isn't exist this method“registerBaidu(String, String)”.
Did i miss something or It just can't work recently?
The problem is in the NotificationHub.jar.
Normally the file you download from the official websites is NotificationHub-0.3.jar. But the method: registerBaidu() is in the NotificationHub-0.4.jar.
So you have to upgrade the library.
I am trying to verify a JWT that I am receiving from Google using GoogleAuthUtil. I am trying to use the code at the bottom of this page. Here is my exact source code:
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
public class Checker {
private final List mClientIDs;
private final String mAudience;
private final GoogleIdTokenVerifier mVerifier;
private final JsonFactory mJFactory;
private String mProblem = "Verification failed. (Time-out?)";
public Checker(String[] clientIDs, String audience) {
mClientIDs = Arrays.asList(clientIDs);
mAudience = audience;
NetHttpTransport transport = new NetHttpTransport();
mJFactory = new JsonFactory();
mVerifier = new GoogleIdTokenVerifier(transport, mJFactory);
}
public GoogleIdToken.Payload check(String tokenString) {
GoogleIdToken.Payload payload = null;
try {
GoogleIdToken token = GoogleIdToken.parse(mJFactory, tokenString);
if (mVerifier.verify(token)) {
GoogleIdToken.Payload tempPayload = token.getPayload();
if (!tempPayload.getAudience().equals(mAudience))
mProblem = "Audience mismatch";
else if (!mClientIDs.contains(tempPayload.getIssuee()))
mProblem = "Client ID mismatch";
else
payload = tempPayload;
}
} catch (GeneralSecurityException e) {
mProblem = "Security issue: " + e.getLocalizedMessage();
} catch (IOException e) {
mProblem = "Network problem: " + e.getLocalizedMessage();
}
return payload;
}
public String problem() {
return mProblem;
}
}
The issue that I'm having is in this line: mJFactory = new JsonFactory();, where I am getting the error Cannot instantiate the type JsonFactory. I'm pretty sure I'm calling the constructor properly and I have all of the libraries imported properly so I don't know why I'm getting this error. If anyone can help me out, that would be great! Let me know if theres any additional info that would be helpful.
EDIT:
Here's the link to the Javadoc
Okay the issue was that I made a small mistake copying the code. JsonFactory is an abstract class, so you need to use the subclass GsonFactory to provide an implementation.
I'm developing an Android app that uses the Dropbox Sync API to upload files. I have already created the app on Dropbox, gotten the APP_KEY and the APP_SECRET. I have included all the necessary libraries, set the proper keys in my activity code and the Manifest. My app is similar to the HelloDropbox sample provided in the documentation, but when I click on the "Link to Dropbox" button which is supposed to display a place to enter my dropbox credentials, nothing happens. Here's the source code:
package com.diamondtrust66.helix.player;
import java.io.File;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.sync.android.DbxAccountManager;
import com.dropbox.sync.android.DbxFile;
import com.dropbox.sync.android.DbxFileInfo;
import com.dropbox.sync.android.DbxFileSystem;
import com.dropbox.sync.android.DbxPath;
public class HelixPlayer extends Activity {
private static final String appKey = "1234-my-key";
private static final String appSecret = "1234-my-secret";
private static final int REQUEST_LINK_TO_DBX = 0;
private TextView mTestOutput;
private Button mLinkButton;
private DbxAccountManager mDbxAcctMgr;
private DropboxAPI<?> mDBApi;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_helix_player);
mTestOutput = (TextView) findViewById(R.id.test_output);
mLinkButton = (Button) findViewById(R.id.link_button);
mLinkButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onClickLinkToDropbox();
}
});
mDbxAcctMgr = DbxAccountManager.getInstance(getApplicationContext(), appKey, appSecret);
}
#Override
protected void onResume() {
super.onResume();
if (mDbxAcctMgr.hasLinkedAccount()) {
showLinkedView();
doDropboxTest();
} else {
showUnlinkedView();
}
}
private void showLinkedView() {
mLinkButton.setVisibility(View.GONE);
mTestOutput.setVisibility(View.VISIBLE);
}
private void showUnlinkedView() {
mLinkButton.setVisibility(View.VISIBLE);
mTestOutput.setVisibility(View.GONE);
}
private void onClickLinkToDropbox() {
mDbxAcctMgr.startLink((Activity)this, REQUEST_LINK_TO_DBX);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_LINK_TO_DBX) {
if (resultCode == Activity.RESULT_OK) {
doDropboxTest();
} else {
Toast.makeText(getApplicationContext(), "FAILURE", Toast.LENGTH_LONG).show();
mTestOutput.setText("Link to Dropbox failed or was cancelled.");
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void doDropboxTest() {
try {
final String TEST_DATA = "Hello Dropbox";
final String TEST_FILE_NAME = "be like that.mp3";
DbxPath testPath = new DbxPath(DbxPath.ROOT, TEST_FILE_NAME);
// Create DbxFileSystem for synchronized file access.
DbxFileSystem dbxFs = DbxFileSystem.forAccount(mDbxAcctMgr.getLinkedAccount());
// Print the contents of the root folder. This will block until we can
// sync metadata the first time.
List<DbxFileInfo> infos = dbxFs.listFolder(DbxPath.ROOT);
mTestOutput.setText("\nContents of app folder:\n");
for (DbxFileInfo info : infos) {
mTestOutput.append(" " + info.path + ", " + info.modifiedTime + '\n');
}
// Create a test file only if it doesn't already exist.
if (!dbxFs.exists(testPath)) {
DbxFile testFile = dbxFs.create(testPath);
try {
File myFile = new File("/mnt/sdcard/alarms/be like that.mp3");
//testFile.writeString(TEST_DATA);
testFile.writeFromExistingFile(myFile, false);
} finally {
testFile.close();
}
mTestOutput.append("\nCreated new file '" + testPath + "'.\n");
}
// Read and print the contents of test file. Since we're not making
// any attempt to wait for the latest version, this may print an
// older cached version. Use getSyncStatus() and/or a listener to
// check for a new version.
/*if (dbxFs.isFile(testPath)) {
String resultData;
DbxFile testFile = dbxFs.open(testPath);
try {
resultData = testFile.readString();
} finally {
testFile.close();
}
mTestOutput.append("\nRead file '" + testPath + "' and got data:\n " + resultData);
} else if (dbxFs.isFolder(testPath)) {
mTestOutput.append("'" + testPath.toString() + "' is a folder.\n");
}*/
} catch (IOException e) {
mTestOutput.setText("Dropbox test failed: " + e);
}
}
}
Are you able to run the unmodified Hello Dropbox example on the same emulator/device where you're experiencing this problem? You can try replacing the app key/secret in the sample with your own as well. If those also fail, it may be there's something wrong with the configuration of your device which is keeping the API from launching a browser to complete authentication. If the example works, but your app doesn't, then I'd suspect something misconfigured there. Can you check with a log statement whether your call to startLink() is actually happening? Do you see anything appear in LogCat after that point?
The best way to debug this further might be to open a suppot ticket. Use the API Support link here: https://www.dropbox.com/developers
I ran into the same problem, the startLink() was doing nothing when I tried to use the same dropbox app credentials I was using with another android app my device had installed (although not running), but it didn't work. So you have two options: Uninstall any other android app using the same credentials OR create another dropbox app and renew the set of app/pass keys. Only then the Dropbox Login Dialog appears.