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.
Related
I am trying to find a way to have a tablet basically auto-accept/give permission to accept an incoming Bluetooth Share file transferred from a laptop to my Nexus Android device. Since the Android bluetooth system itself does not support this feature, I was wondering if this could be done programmatically using an Android application that listened for the notification and accepted it for me.
MUCH EASIER WAY
If you have a rooted device and use XPosed Framework, your goal can be achieved much easier.
You Need not implement your own bluetooth server nor kill the original BT service, which are very bothering!!!
xposed tutorial link.
Try this code.
import android.util.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial implements IXposedHookLoadPackage
{
private String TAG="TUTORIAL";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth"))
{
Log.i(TAG,"Not: "+lpparam.packageName);
return;
}
Log.i(TAG,"Yes "+lpparam.packageName);
findAndHookMethod("com.android.bluetooth.opp.BluetoothOppManager", lpparam.classLoader, "isWhitelisted", String.class,new XC_MethodHook() {
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.v(TAG,"HOOK DONE");
param.setResult(true); /* you can compare the sender address(String) with your computer and determine if you return true or just allow the original method to be called after this returns.*/
}
});
}
}
I tested and it works fine:)
Links
Dropbox link of the auto accepting app
Dropbox link of the project files (zip)
Xposed apk site
Towelroot site to root your phone
Background(Original answer)
As I commented above, you bay be able to, and I tried and succeeded in blocking (though not receiving) with this code.
import android.util.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import java.io.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial implements IXposedHookLoadPackage
{
private String TAG="TUTORIAL";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth"))
{
Log.i(TAG,"Not: "+lpparam.packageName);
return;
}
Log.i(TAG,"Yes "+lpparam.packageName);
findAndHookMethod("com.android.bluetooth.opp.BluetoothOppService", lpparam.classLoader, "startSocketListener", new XC_MethodHook() {
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.v(TAG,"HOOK DONE");
param.setResult(null);
}
});
}
}
The code above hooks the method startListenerSocket() of com.android.bluetooth.BluetoothOppService and prevents the original method from being called by the line param.setResult(null);
Refer to here to see the full code of com.android.bluetooth.BluetoothOppService.java and you will understand the operation.
And the code you can start from is shown below.
import android.util.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial implements IXposedHookLoadPackage
{
private String TAG="TUTORIAL";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth"))
{
Log.i(TAG,"Not: "+lpparam.packageName);
return;
}
Log.i(TAG,"Yes "+lpparam.packageName);
findAndHookMethod("com.android.bluetooth.opp.BluetoothOppObexServerSession", lpparam.classLoader, "onPut", new XC_MethodHook() {
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.v(TAG,"HOOK DONE");
Class c=param.thisObject.getClass();
}
});
}
}
This code hooks the onPut method of com.android.bluetooth. BluetoothOppObexServerSession linked here. I either am newbie to xposed framework but I hope my answer helped.
I had the same issues you asked and partially solved the problem by implementing my custom OBEX server and manually / programmatically(with ps|grep and su kill pid) killing the native BluetoothOppService. But I will either try the idea of hooking and directly executing my code.
And to help you customize OBEX server session I post my implementation below.
#Override
public int onPut(Operation op)
{
if (D)
{
Log.d(TAG, "onPut " + op.toString());
}
HeaderSet request;
String name, mimeType;
Long length;
String extension=null;// type;
int obexResponse = ResponseCodes.OBEX_HTTP_OK;
String destination;
if (mTransport instanceof BluetoothObexTransport)
{
destination = ((BluetoothObexTransport) mTransport).getRemoteAddress();
}
else
{
destination = "FF:FF:FF:00:00:00";
}
boolean isWhitelisted =IsWhitelisted(destination);
try
{
boolean preReject = false;
request = op.getReceivedHeader();
if (V)
{
// Constants.logHeader(request);
}
name = (String) request.getHeader(HeaderSet.NAME);
length = (Long) request.getHeader(HeaderSet.LENGTH);
mimeType = (String) request.getHeader(HeaderSet.TYPE);
if (length == 0)
{
if (D)
{
Log.w(TAG, "length is 0, reject the transfer");
}
preReject = true;
obexResponse = ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED;
}
if (name == null || name.isEmpty())
{
if (D)
{
Log.w(TAG, "name is null or empty, reject the transfer");
}
preReject = true;
obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST;
}
int dotIndex = name.lastIndexOf(".");
if (dotIndex > 0)
{
extension = name.substring(dotIndex + 1).toLowerCase();
}
// Reject policy: anything outside the "white list" plus unspecified
// MIME Types. Also reject everything in the "black list".
// if (!preReject && (mimeType == null || (!isWhitelisted && !Constants.mimeTypeMatches(
// mimeType, Constants.ACCEPTABLE_SHARE_INBOUND_TYPES))
// || Constants.mimeTypeMatches(mimeType,
// Constants.UNACCEPTABLE_SHARE_INBOUND_TYPES))) {
// if (D) {
// Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer");
// }
// preReject = true;
// obexResponse = ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
// }
if (preReject && obexResponse != ResponseCodes.OBEX_HTTP_OK)
{
// some bad implemented client won't send disconnect
return obexResponse;
}
}
catch (IOException e)
{
Log.e(TAG, "get getReceivedHeaders error " + e);
return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
}
int status = receiveFile(destination, name, extension, length, op);
/*
* TODO map status to obex response code
*/
if (status != BluetoothShare.STATUS_SUCCESS)
{
obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
Log.d(TAG, "MIME TYPE)" + mimeType);
return obexResponse;
}
I just removed some rejecting codes from the original one.
Also to look at my full code please refer to my git repository.
I also thank the contributors to the android project!
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());
}
}
};
I am trying to access the google drive through android app. I have turned on the Drive API and Drive SDK in Google Developer Console and generated a OAuth Client id.
Inserted the Client key in AndroidManifest.xml as
<meta-data
android:name="com.google.android.apps.drive.APP_ID"
android:value=id="***CLIENT_KEY***" />
And a permission as
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.INTERNET"/>
This is the code which I am trying to run (Originally from here)
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi.DriveContentsResult;
import com.google.android.gms.drive.MetadataChangeSet;
/**
* Android Drive Quickstart activity. This activity takes a photo and saves it
* in Google Drive. The user is prompted with a pre-made dialog which allows
* them to choose the file location.
*/
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "android-drive-quickstart";
private static final int REQUEST_CODE_CAPTURE_IMAGE = 1;
private static final int REQUEST_CODE_CREATOR = 2;
private static final int REQUEST_CODE_RESOLUTION = 3;
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;
/**
* Create a new file and save it to Drive.
*/
private void saveFileToDrive() {
// Start by creating a new contents, and setting a callback.
Log.i(TAG, "Creating new contents.");
final Bitmap image = mBitmapToSave;
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
// If the operation was not successful, we cannot do anything
// and must
// fail.
if (!result.getStatus().isSuccess()) {
Log.i(TAG, "Failed to create new contents.");
return;
}
// Otherwise, we can write our data to the new contents.
Log.i(TAG, "New contents created.");
// Get an output stream for the contents.
OutputStream outputStream = result.getDriveContents().getOutputStream();
// Write the bitmap data from it.
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
try {
outputStream.write(bitmapStream.toByteArray());
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.");
}
// Create the initial metadata - MIME type and title.
// Note that the user will be able to change the title later.
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("image/jpeg").setTitle("Android Photo.png").build();
// Create an intent for the file chooser, and start it.
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialDriveContents(result.getDriveContents())
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.");
}
}
});
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Connect the client. Once connected, the camera is launched.
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_CAPTURE_IMAGE:
// Called after a photo has been taken.
if (resultCode == Activity.RESULT_OK) {
// Store the image data as a bitmap for writing later.
mBitmapToSave = (Bitmap) data.getExtras().get("data");
}
break;
case REQUEST_CODE_CREATOR:
// Called after a file is saved to Drive.
if (resultCode == RESULT_OK) {
Log.i(TAG, "Image successfully saved.");
mBitmapToSave = null;
// Just start the camera again for another photo.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
}
break;
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
if (mBitmapToSave == null) {
// This activity has no UI of its own. Just start the camera.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
return;
}
saveFileToDrive();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
}
This is the error I am getting
02-19 18:58:18.204 27221-27221/com.gajendraprofile.drive I/android-drive-quickstart﹕ GoogleApiClient connection failed: ConnectionResult{statusCode=INTERNAL_ERROR, resolution=null}
02-19 18:58:47.584 27431-27431/com.gajendraprofile.drive I/android-drive-quickstart﹕ GoogleApiClient connection failed: ConnectionResult{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{21b27910: android.os.BinderProxy#21b00a7c}}
02-19 18:58:51.564 27431-27431/com.gajendraprofile.drive I/android-drive-quickstart﹕ GoogleApiClient connection failed: ConnectionResult{statusCode=INTERNAL_ERROR, resolution=null}`
Am I making any errors above? Are there any better simple example to access Google Drive from Android?
The Quick Start you play with as as simple as it gets, to answer you question.
But it may be outdated (I don't know, last time I ran it was 8 months ago). GooPlayServices are on the 6.5.+ version and last update of that code was half a year ago. I have some code on GitHub that I can't claim is simpler, but (probably) more in line with current lib version. It is a bit broader and deals with both GDAA and REST APIs, as well as with the Google account pick process. If you use Android Studio, you should be able to make use of it.
Just a few points:
You have go through the Developers Console stuff. Basically you must have your 'package name' / SHA1 registered. I usually register both debug and release SHA1s and double check if my APKs are actually correct - see SO 28532206
Look at SO 28439129 here to get some sense what is involved in connecting to GooDrive
If you use the code I mentioned, make sure you environment is in line with dependencies in 'build.gradle' there (my SDK Manager shows GooPlaySvcs 21, which is 'com.google.android.gms:play-services:6.5.87')
Good Luck
This error "GoogleApiClient connection failed: ConnectionResult{statusCode=INTERNAL_ERROR, resolution=null} " occurs if you have not created credentials for your application.
Go to console- https://console.cloud.google.com/apis/credentials
Click on Create Credentials
Select QAuth client ID
Select Application type as Android if you are running from AndroidStudio
Add the projectname, SHA key & package name
Run the project and the application should work.
I faced issue running android-quickstart-master and the issue got resolved after following the above steps
I am working on an android app which facilitate payment through credit card for that I am using CARD.IO SDK for android.
I have integrated the card.io sdk in my code but when I launch the app it's not allowing me to scan any card.It showing a message this device can not use camera to read card numbers
Here is my code:
package org.my.scanExample;
import io.card.payment.CardIOActivity;
import io.card.payment.CreditCard;
import org.my.scanExample.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MyScanActivity extends Activity
{
// You MUST register with card.io to get an app token. Go to https://card.io/apps/new/
private static final String MY_CARDIO_APP_TOKEN = "app_id";
private View v;
final String TAG = getClass().getName();
private Button scanButton;
private TextView resultTextView;
private int MY_SCAN_REQUEST_CODE = 100; // arbitrary int
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
resultTextView = (TextView)findViewById(R.id.resultTextView);
scanButton = (Button)findViewById(R.id.scanButton);
}
#Override
protected void onResume() {
super.onResume();
resultTextView.setText("card.io library version: " + CardIOActivity.sdkVersion() + "\nBuilt: " + CardIOActivity.sdkBuildDate());
if (CardIOActivity.canReadCardWithCamera(this)) {
scanButton.setText("Scan a credit card with card.io");
}
else {
scanButton.setText("Enter credit card information");
onScanPress(v);
}
}
public void onScanPress(View v) {
// This method is set up as an onClick handler in the layout xml
// e.g. android:onClick="onScanPress"
Intent scanIntent = new Intent(this, CardIOActivity.class);
// required for authentication with card.io
scanIntent.putExtra(CardIOActivity.EXTRA_APP_TOKEN, MY_CARDIO_APP_TOKEN);
// customize these values to suit your needs.
scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true); // default: true
scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_CVV, false); // default: false
scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_ZIP, false); // default: false
// hides the manual entry button
// if set, developers should provide their own manual entry mechanism in the app
scanIntent.putExtra(CardIOActivity.EXTRA_SUPPRESS_MANUAL_ENTRY, false); // default: false
// MY_SCAN_REQUEST_CODE is arbitrary and is only used within this activity.
startActivityForResult(scanIntent, MY_SCAN_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String resultStr;
if (data != null && data.hasExtra(CardIOActivity.EXTRA_SCAN_RESULT)) {
CreditCard scanResult = data.getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT);
// Never log a raw card number. Avoid displaying it, but if necessary use getFormattedCardNumber()
resultStr = "Card Number: " + scanResult.getRedactedCardNumber() + "\n";
// Do something with the raw number, e.g.:
// myService.setCardNumber( scanResult.cardNumber );
if (scanResult.isExpiryValid()) {
resultStr += "Expiration Date: " + scanResult.expiryMonth + "/" + scanResult.expiryYear + "\n";
}
if (scanResult.cvv != null) {
// Never log or display a CVV
resultStr += "CVV has " + scanResult.cvv.length() + " digits.\n";
}
if (scanResult.zip != null) {
resultStr += "Zip: " + scanResult.zip + "\n";
}
}
else {
resultStr = "Scan was canceled.";
}
resultTextView.setText(resultStr);
}
}
Exception:
Failed to load native library: couldn't load cardIODecider : indLibrary returned null.
-processor type is not supported
cardIoScanErrorNoDeviceSupport
Typically this happens when the native libraries are not in the project's libs directory. The structure should look as follows, which will happen if you unzip the sdk into your project's directory.
$ ls libs/*
libs/card.io.jar
libs/armeabi:
libcardioDecider.so
libs/armeabi-v7a:
libcardioDecider.so libcardioRecognizer.so libcardioRecognizer_tegra2.so libopencv_core.so libopencv_imgproc.so
libs/mips:
libcardioDecider.so
libs/x86:
libcardioDecider.so
I am new to android, i want to download the files from FTPs server, On emulater i am able to download files but when i try on target board it is giving error at ftp.auth(SSLFTPClient.AUTH_TLS);
Below is the my code, please suggest me where i am wrong.
package com.android.ftp;
import java.io.File;
import android.app.Activity;
import android.os.Bundle;
import com.enterprisedt.net.ftp.FTPClientInterface;
import com.enterprisedt.net.ftp.FTPConnectMode;
import com.enterprisedt.net.ftp.FTPTransferType;
import com.enterprisedt.net.ftp.ssl.SSLFTPClient;
import com.enterprisedt.util.debug.Level;
import com.enterprisedt.util.debug.Logger;
public class Ftp_testActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String host = "ftp.xyz.com";
String username = "abcd";
String password = "pqr";
String filename = "/mnt/sdcard/video1/747.3gp";
// set up logger so that we get some output
Logger log = Logger.getLogger(Ftp_testActivity.class);
Logger.setLevel(Level.INFO);
SSLFTPClient ftp = null;
try {
// create client
log.info("Creating FTPS (explicit) client");
ftp = new SSLFTPClient();
// disable standard SSL closure
log.info("Setting configuration flags");
ftp.setConfigFlags(SSLFTPClient.ConfigFlags.DISABLE_SSL_CLOSURE);
// set remote host
log.info("Setting remote host");
ftp.setRemoteHost(host);
ftp.setRemotePort(21);
// turn off server validation
log.info("Turning off server validation");
ftp.setValidateServer(false);
// connect to the server
log.info("Connecting to server " + host);
ftp.connect();
// switch to SSL on control channel
log.info("Switching to FTPS (explicit mode)");
ftp.auth(SSLFTPClient.AUTH_TLS);
// log in
log.info("Logging in with username=" + username + " and password="
+ password);
ftp.login(username, password);
log.info("Logged in");
ftp.setConnectMode(FTPConnectMode.PASV);
ftp.setType(FTPTransferType.ASCII);
putGetDelete(filename, ftp);
log.info("Successfully transferred in ASCII mode");
// Shut down client
log.info("Quitting client");
ftp.quit();
log.info("Example complete");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void putGetDelete(String name, FTPClientInterface ftp)
throws Exception {
ftp.put(name, name);
ftp.get(name + ".copy", name);
ftp.delete(name);
File file = new File(name + ".copy");
file.delete();
}
}
You should try:
ftp.setRemotePort(990);
where 990 is port SSL default.