cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
What’s new: end-to-end encryption, Replay and Dash updates. Find out more about these updates, new features and more here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

my android app not uploading photo directly to Dropbox app folder using API

my android app not uploading photo directly to Dropbox app folder using API

Ghost Mjrm
Explorer | Level 4

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 check the Dropbox app i cannot find any photo

this is my app code included the authentication method that i used

package com.example.decamera;

import android.Manifest;
import android.content.pm.PackageManager;
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 android.net.Uri;
import android.util.Log;



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.lifecycle.LifecycleOwner;

import com.dropbox.core.DbxRequestConfig;
import com.dropbox.core.v2.files.FileMetadata;
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.IOException;
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 int LOCATION_PERMISSION_REQUEST = 101;
private static final String[] REQUIRED_CAMERA_PERMISSIONS = new String[]{Manifest.permission.CAMERA};
private static final String[] REQUIRED_LOCATION_PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};

private PreviewView previewView;
private ImageCapture imageCapture;
private TextView addressTextView;

private ExecutorService cameraExecutor = Executors.newSingleThreadExecutor();
private FusedLocationProviderClient fusedLocationProviderClient;
private Geocoder geocoder;

// Dropbox variables
private static final String ACCESS_TOKEN = "my access token";

private DbxRequestConfig config;
private com.dropbox.core.v2.DbxClientV2 dropboxClient;

@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());

// Initialize Dropbox variables
config = DbxRequestConfig.newBuilder("de_camera_app").build();
dropboxClient = new com.dropbox.core.v2.DbxClientV2(config, ACCESS_TOKEN);

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()) // Add this line
.build();

// Re-bind use cases to the camera
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 {
// Request location permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_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) {
captureAndUploadToDropbox(); // Call the new method
}
}

private void captureAndUploadToDropbox() {
// Capture the image and directly upload it to Dropbox
ImageCapture.OutputFileOptions outputFileOptions =
new ImageCapture.OutputFileOptions.Builder(createImageFile()).build();

imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@Nullable ImageCapture.OutputFileResults outputFileResults) {
Uri savedUri = outputFileResults.getSavedUri();

if (savedUri != null) {
File savedPhoto = new File(savedUri.getPath());

// Upload the photo to Dropbox
uploadToDropbox(savedPhoto);

// Notify the user
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Photo saved and uploaded successfully", Toast.LENGTH_SHORT).show());
} else {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error getting saved file URI", Toast.LENGTH_SHORT).show());
}
}

@Override
public void onError(@NonNull ImageCaptureException exception) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error capturing image: " + exception.getMessage(), Toast.LENGTH_SHORT).show());
}
});
}


private void uploadToDropbox(File photoFile) {
try {
// Get the file name
String fileName = photoFile.getName();

// Log the file path before upload
Log.d("DropboxUpload", "Uploading file: " + photoFile.getAbsolutePath());

// Open the photo file
FileInputStream fis = new FileInputStream(photoFile);

// Specify the remote path on Dropbox where you want to upload the file
String remotePath = "/Apps/Bau" + fileName; // Replace "Bau" with your desired folder name

// Upload the photo file
FileMetadata metadata = dropboxClient.files().uploadBuilder(remotePath)
.uploadAndFinish(fis);

// You can handle the metadata response if needed
// metadata.getName(), metadata.getSize(), etc.

runOnUiThread(() -> Toast.makeText(MainActivity.this, "Photo uploaded to Dropbox successfully", Toast.LENGTH_SHORT).show());
} catch (Exception e) {
e.printStackTrace();
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) {
return File.createTempFile(imageFileName, ".jpg", storageDir);
} 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", 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();
}
} else if (requestCode == LOCATION_PERMISSION_REQUEST) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLastLocation();
} else {
runOnUiThread(() -> Toast.makeText(this, "Location permissions not granted.", Toast.LENGTH_SHORT).show());
}
}
}
}

 

1 Accepted Solution

Accepted Solutions

Здравко
Legendary | Level 20

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.

View solution in original post

16 Replies 16

Здравко
Legendary | Level 20

@Ghost Mjrm wrote:

...

but its tell me that the photo uploaded successfully but when i check the Dropbox app i cannot find any photo

...


Hi @Ghost Mjrm,

Do you understand that in you code message "Photo saved and uploaded successfully" may be preceded by "Error uploading to Dropbox: "? Do you receive double confirmation of success or just one? 🧐

If everything was Ok, Did you take a look in your "/Apps/Bau" folder only? If so, take a look in "/Apps/Bau/Apps" too. 😉 Are your missing photos there?

Hope this helps.

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

Ghost Mjrm
Explorer | Level 4

i have made some changes to my code to show only confirmation in uploading success or not and when i use the app and capture image message pop up und tell me error uploading to dropbox:null this is my new code so the upload process dosn´t success 

package com.example.decamera;

import android.Manifest;
import android.content.pm.PackageManager;
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 android.net.Uri;
import android.util.Log;



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.lifecycle.LifecycleOwner;

import com.dropbox.core.DbxRequestConfig;
import com.dropbox.core.v2.files.FileMetadata;
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.IOException;
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 int LOCATION_PERMISSION_REQUEST = 101;
private static final String[] REQUIRED_CAMERA_PERMISSIONS = new String[]{Manifest.permission.CAMERA};
private static final String[] REQUIRED_LOCATION_PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};

private PreviewView previewView;
private ImageCapture imageCapture;
private TextView addressTextView;

private ExecutorService cameraExecutor = Executors.newSingleThreadExecutor();
private FusedLocationProviderClient fusedLocationProviderClient;
private Geocoder geocoder;

// Dropbox variables
private static final String ACCESS_TOKEN = "sl.BqXWiazZAvf1uR-ONm9kH7XTjxew29xKWUh46mSxUg5CcRKKImYicad6kMsgMCLDHHNeP2mcyww-XWHNX2jP2CQPIFnHOfTu--sTcmTl5DgrgdH_Cb1UiR8V5tl3-q4L9MgywIHeaIFOEWfRIOlylMs";

private DbxRequestConfig config;
private com.dropbox.core.v2.DbxClientV2 dropboxClient;

@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());

// Initialize Dropbox variables
config = DbxRequestConfig.newBuilder("de_camera_app").build();
dropboxClient = new com.dropbox.core.v2.DbxClientV2(config, ACCESS_TOKEN);

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()) // Add this line
.build();

// Re-bind use cases to the camera
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 {
// Request location permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_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) {
captureAndUploadToDropbox(); // Call the new method
}
}

private void captureAndUploadToDropbox() {
// Capture the image and directly upload it to Dropbox
ImageCapture.OutputFileOptions outputFileOptions =
new ImageCapture.OutputFileOptions.Builder(createImageFile()).build();

imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@Nullable ImageCapture.OutputFileResults outputFileResults) {
Uri savedUri = outputFileResults.getSavedUri();

if (savedUri != null) {
File savedPhoto = new File(savedUri.getPath());

// Upload the photo to Dropbox
uploadToDropbox(savedPhoto);
} else {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error getting saved file URI", Toast.LENGTH_SHORT).show());
}
}

@Override
public void onError(@NonNull ImageCaptureException exception) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error capturing image: " + exception.getMessage(), Toast.LENGTH_SHORT).show());
}
});
}



private void uploadToDropbox(File photoFile) {
try {
// Get the file name
String fileName = photoFile.getName();

// Log the file path before upload
Log.d("DropboxUpload", "Uploading file: " + photoFile.getAbsolutePath());

// Open the photo file
FileInputStream fis = new FileInputStream(photoFile);

// Specify the remote path on Dropbox where you want to upload the file
String remotePath = "/Apps/Bau" + fileName; // Replace "Bau" with your desired folder name

// Upload the photo file
FileMetadata metadata = dropboxClient.files().uploadBuilder(remotePath)
.uploadAndFinish(fis);

// You can handle the metadata response if needed
// metadata.getName(), metadata.getSize(), etc.

runOnUiThread(() -> Toast.makeText(MainActivity.this, "Photo uploaded to Dropbox successfully", Toast.LENGTH_SHORT).show());
} catch (Exception e) {
e.printStackTrace();
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) {
return File.createTempFile(imageFileName, ".jpg", storageDir);
} 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", 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();
}
} else if (requestCode == LOCATION_PERMISSION_REQUEST) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLastLocation();
} else {
runOnUiThread(() -> Toast.makeText(this, "Location permissions not granted.", Toast.LENGTH_SHORT).show());
}
}
}
}

Здравко
Legendary | 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! 👆

Здравко
Legendary | Level 20

@Ghost Mjrm wrote:

... und tell me error uploading to dropbox:null ...

 Hm..🤔 Try find out where exactly the exception comes from (set middle points throughout your code). Perform intensive logging in your uploadToDropbox method in every line and split the composite lines.

Ghost Mjrm
Explorer | 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  

Здравко
Legendary | Level 20

Just performing OAuth flow and using "offline" as type will give you refresh token that doesn't expire. 😉

Greg-DB
Dropbox 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 Mjrm
Explorer | 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();
}
}
}
}
Need more support?
Who's talking

Top contributors to this post

  • User avatar
    Ghost Mjrm Explorer | Level 4
  • User avatar
    Greg-DB Dropbox Staff
What do Dropbox user levels mean?