You might see that the Dropbox Community team have been busy working on some major updates to the Community itself! So, here is some info on what’s changed, what’s staying the same and what you can expect from the Dropbox Community overall.
Forum Discussion
Ghost Mjrm
12 months agoExplorer | Level 4
my android app not uploading photo directly to Dropbox app folder using API
i have created android app and i add the API and the SDK to it to contact with my Dropbox app folder to automatically uploading photo but its tell me that the photo uploaded successfully but when i ...
- 12 months ago
More details about that error would be useful. It's not clear what doesn't work for you actually. The refresh token will just 'extend' your authentication 'life' (if could be said so), nothing more.
Ghost Mjrm
Explorer | Level 4
hi
you have right i noticed that now
its better to do one confirmation message what should i delete and what should i remove can you tell me what is better and then i can see the right confirmation on the screen
Best Regards
Здравко
12 months agoLegendary | Level 20
Ghost Mjrm, there is no single right decision. It's matter of design decision and you can make it as you like.
Something else: Don't forget that access token (the one you use in your code) is short lived! 👆
- Ghost Mjrm12 months agoExplorer | Level 4
thank you so much to noticing me one more once but every time should i update my access token to make the app working again ? is there any solution for that i want to give this app to employer to use it and give me photo every time 24 hours per day
one more question i have edit my access token but the problem is still when i take photo it tell me error uploading to dropbox:null
i have checked my app Dropbox folder and i cannot find anything
Best Regards
- Здравко12 months agoLegendary | Level 20
Just performing OAuth flow and using "offline" as type will give you refresh token that doesn't expire. 😉
- Ghost Mjrm12 months agoExplorer | Level 4
can you explain the steps to me i lost in the internet searching for a solution to my situation this is my code
package com.example.decamera;
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.exifinterface.media.ExifInterface;
import androidx.lifecycle.LifecycleOwner;
import com.dropbox.core.DbxRequestConfig;
import com.dropbox.core.v2.DbxClientV2;
import com.dropbox.core.v2.files.WriteMode;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int CAMERA_PERMISSION_REQUEST = 100;
private static final String[] REQUIRED_CAMERA_PERMISSIONS = new String[]{Manifest.permission.CAMERA};
private static final String DROPBOX_ACCESS_TOKEN = "here should i input my access token but it changend everytime"; // Replace with your Dropbox access token
private PreviewView previewView;
private ImageCapture imageCapture;
private TextView addressTextView;
private ExecutorService cameraExecutor = Executors.newSingleThreadExecutor();
private FusedLocationProviderClient fusedLocationProviderClient;
private Geocoder geocoder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
previewView = findViewById(R.id.previewView);
ImageButton captureButton = findViewById(R.id.captureButton);
addressTextView = findViewById(R.id.addressTextView);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
geocoder = new Geocoder(this, Locale.getDefault());
captureButton.setOnClickListener(this);
if (allPermissionsGranted()) {
startCamera();
getLastLocation();
} else {
ActivityCompat.requestPermissions(this, REQUIRED_CAMERA_PERMISSIONS, CAMERA_PERMISSION_REQUEST);
}
}
private void startCamera() {
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
bindPreview(cameraProvider);
} catch (Exception e) {
e.printStackTrace();
}
}, ContextCompat.getMainExecutor(this));
}
private void bindPreview(ProcessCameraProvider cameraProvider) {
Preview preview = new Preview.Builder().build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview);
preview.setSurfaceProvider(previewView.getSurfaceProvider());
imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetRotation(previewView.getDisplay().getRotation())
.build();
cameraProvider.unbindAll();
cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageCapture);
}
private void getLastLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
updateAddress(location);
}
}
});
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, CAMERA_PERMISSION_REQUEST);
}
}
private void updateAddress(Location location) {
try {
List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
if (addresses != null && addresses.size() > 0) {
Address address = addresses.get(0);
String fullAddress = address.getAddressLine(0);
addressTextView.setText(fullAddress);
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.captureButton) {
captureImage();
}
}
private void captureImage() {
File photoFile = createImageFile();
if (photoFile != null) {
ImageCapture.OutputFileOptions outputFileOptions =
new ImageCapture.OutputFileOptions.Builder(photoFile).build();
imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@Nullable ImageCapture.OutputFileResults outputFileResults) {
combineImageWithAddress(photoFile, addressTextView.getText().toString());
uploadToDropbox(photoFile); // Upload to Dropbox
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error capturing image: " + exception.getMessage(), Toast.LENGTH_SHORT).show());
}
});
} else {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error creating photo file", Toast.LENGTH_SHORT).show());
}
}
private void combineImageWithAddress(File photoFile, String addressText) {
Bitmap photoBitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
// Check the orientation of the image and rotate it if needed
int rotation = getRotationAngle(photoFile.getAbsolutePath());
if (rotation != 0) {
photoBitmap = rotateBitmap(photoBitmap, rotation);
}
Bitmap combinedBitmap = photoBitmap.copy(photoBitmap.getConfig(), true);
Canvas canvas = new Canvas(combinedBitmap);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(150); // Adjust this value according to your preference
paint.setAntiAlias(true);
// Set the font to bold
paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
// Set the coordinates for the left bottom corner
float x = 50;
float y = combinedBitmap.getHeight() - 50;
canvas.drawText(addressText, x, y, paint);
saveCombinedImage(combinedBitmap, photoFile);
}
private int getRotationAngle(String imagePath) {
ExifInterface exifInterface;
try {
exifInterface = new ExifInterface(imagePath);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
default:
return 0;
}
}
private Bitmap rotateBitmap(Bitmap bitmap, int angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
private void saveCombinedImage(Bitmap combinedBitmap, File photoFile) {
try {
FileOutputStream out = new FileOutputStream(photoFile);
combinedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error combining image with address: " + e.getMessage(), Toast.LENGTH_SHORT).show());
}
}
private void uploadToDropbox(File photoFile) {
// Check if the file exists before attempting to upload
if (photoFile == null || !photoFile.exists()) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error: Photo file does not exist", Toast.LENGTH_SHORT).show());
return;
}
// Set up Dropbox client
DbxRequestConfig config = DbxRequestConfig.newBuilder("Decamera").build();
DbxClientV2 client = new DbxClientV2(config, DROPBOX_ACCESS_TOKEN);
try {
// Specify the path in Dropbox where you want to upload the file
String remotePath = "/Decamera/" + photoFile.getName();
// Open the photo file for reading
try (InputStream in = new FileInputStream(photoFile)) {
// Upload the file to Dropbox
client.files().uploadBuilder(remotePath)
.withMode(WriteMode.ADD)
.uploadAndFinish(in); // This line was missing
// Display a success message
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Photo uploaded to Dropbox", Toast.LENGTH_SHORT).show());
}
} catch (Exception e) {
e.printStackTrace();
// Handle upload errors
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error uploading to Dropbox: " + e.getMessage(), Toast.LENGTH_SHORT).show());
}
}
private File createImageFile() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
try {
if (storageDir != null) {
File tempFile = File.createTempFile(imageFileName, ".jpg", storageDir);
// Log the file path for debugging
System.out.println("File path: " + tempFile.getAbsolutePath());
return tempFile;
} else {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error creating storage directory", Toast.LENGTH_SHORT).show());
}
} catch (IOException e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error creating photo file: " + e.getMessage(), Toast.LENGTH_SHORT).show());
}
return null;
}
private boolean allPermissionsGranted() {
for (String permission : REQUIRED_CAMERA_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION_REQUEST) {
if (allPermissionsGranted()) {
startCamera();
getLastLocation();
} else {
runOnUiThread(() -> Toast.makeText(this, "Camera permissions not granted.", Toast.LENGTH_SHORT).show());
finish();
}
}
}
}
- Greg-DB12 months agoDropbox Staff
Ghost Mjrm Здравко is correct; for long-term access, you can request "offline" access, in which case the app receives a "refresh token" that can be used to retrieve new short-lived access tokens as needed, without further manual user intervention. Refresh tokens do not expire automatically and can be used repeatedly. You can find more information in the OAuth Guide and authorization documentation. There's a basic outline of processing this flow in this blog post which may serve as a useful example.
The official Dropbox Java SDK can actually handle the process for you automatically, as long as you supply the necessary credentials, e.g., as shown retrieved in the examples here. For instance, for a client-side app, such as a desktop app, you should use the PKCE flow, e.g., as shown here. That allows you to make and save a DbxCredential with a refresh token as shown here. With that, you can make API calls like shown here.- Ghost Mjrm12 months agoExplorer | Level 4
one more thing i got error upload to Dropbox:null and i didn't find the solution yet so i considered that if i make the refresh token doesn't expire it could fix my problem
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
5,882 PostsLatest Activity: 3 years agoIf you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X or Facebook.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!