Geotags on Images in Android Studio (GeoTagImage)

Ashish Dangi
5 min readJun 11, 2023

Hello everyone,

In this blog I am going to guide you to how to add Geo tags or GPS location on the images clicked by the device camera. This is an android library to import in the android studio project and then just do some basic code. So here is the GeoTagImage Library for android app project.

So First of all I am pointing out the key features of this library.

Key Features :

  1. Request camera & location permission callback by itself.
  2. Show location and address.
  3. Show Lat Longs.
  4. Show author name.
  5. Show app name.
  6. Show Google map snapshot.
  7. Set Image Quality.
  8. Set Image Extension Type.
  9. Set Custom Typeface.

Handle Visibilities :

  1. Show/hide app name — showAppName()
  2. Show/hide author name — showAuthorName()
  3. Show/hide google map — showGoogleMap()
  4. Show/hide Lat Longs — showLatLng()

So lets start, the brief summary of these points :

  1. Request Camera & Location permission — The library can ask the permission by itself by using permission callback listener. Only the result need to handle in the activity or the fragment by using OnRequestPermissionResult().
  2. Show Location & Address — The library can draw device’s current location such as sub-admin area, locality and country name along with complete address.
  3. Show Lat Longs — The library can also draw device’s current coordinates such as latitude and longitude.
  4. Show Author Name — The library can draw author (clicked by) name on the image. You need to add method setAuthorName(“name”) and showAuthorName(true) as by default the author name visibility is INVISIBLE.
  5. Show App Name — The library can draw app name also in which this library has been imported. You need to set visibility of this by using showAppName(true).
  6. Show Google Map — The library can show google map snapshot of device’s current location along with marker. It depends on your project is linked with google map SDK or not. If not then the visibility of google map snapshot will be invisible by default.
  7. Set Image Quality — The library has a feature to set image quality. By default the image quality will be STANDARD size and LOW & HIGH qualities are optional which can be use by setImageQuality() method.
  8. Set Image Extension Type — The library has a feature to set image extension. By default the image quality will be PNG and JPG & JPEG formats are optional which can be use by setImageExtension() method.
  9. Set Custom Typeface — The library has a feature to set custom type face font by setCustomTypeface() method.

Start Implementation of the library :

Gradle

Add repository in your build.gradle (project-level) file :

allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}

OR

in your settings.gradle

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
...
maven { url "https://jitpack.io" }
}
}

Add dependency :

Add dependency in your build.gradle (module-level) file :

dependencies{

implementation 'com.github.dangiashish:GeoTagImage:1.1.0'
}

Add file provider in AndroidManifest.xml :

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>

Create an xml file for path provider @xml/provider_path.xml :

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

Java : MainActivity.java :

public class MainActivity extends AppCompatActivity implements PermissionCallback {
private ImageView ivCamera, ivImage, ivClose;
private static String imageStoragePath;
public static final String IMAGE_EXTENSION = ".jpg";
private Uri fileUri;
private static final int CAMERA_IMAGE_REQUEST_CODE = 2000;
private static final int PERMISSION_REQUEST_CODE = 100;

static FragmentActivity mContext;
private GeoTagImage geoTagImage;
private PermissionCallback permissionCallback;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// initialize the context
mContext = MainActivity.this;
// initialize the permission callback listener
permissionCallback = this;

// initialize the GeoTagImage class object with context and callback
// use try/catch block to handle exceptions.
try {
geoTagImage = new GeoTagImage(mContext, permissionCallback);
} catch (GTIException e) {
throw new RuntimeException(e);
}

// initialize the xml buttons.
ivCamera = findViewById(R.id.ivCamera);
ivImage = findViewById(R.id.ivImage);
ivClose = findViewById(R.id.ivClose);

// setOnClickListener on camera button.
ivCamera.setOnClickListener(click -> {
// first check permission for camera and location by using GTIPermission class.
if (GTIPermissions.checkCameraLocationPermission(mContext)) {

// if permissions are granted, than open camera.
openCamera();

} else {
// otherwise request for the permissions by using GTIPermission class.
GTIPermissions.requestCameraLocationPermission(mContext, PERMISSION_REQUEST_CODE);
}
});
}
}

openCamera()

    // if permissions are granted for camera and location.
private void openCamera() {
// call Intent for ACTION_IMAGE_CAPTURE which will redirect to device camera.
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

// create a file object
File file;

// before adding GeoTags, generate or create an original image file
// TODO-Note : we need to create an original image to add geotags by copying this file.
file = GTIUtility.generateOriginalFile(mContext, IMAGE_EXTENSION);
if (file != null) {
// if file has been created, then will catch its path for future reference.
imageStoragePath = file.getPath();
}

// now get Uri from this created image file by using GTIUtility.getFileUri() function.
fileUri = GTIUtility.getFileUri(mContext, file);

// pass this uri file into intent filters while opening camera.
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

// call startActivityForResult method by passing the intent filter with a request code.
startActivityForResult(intent, CAMERA_IMAGE_REQUEST_CODE);
}

Handle request permission result

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);

if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
geoTagImage.handlePermissionGrantResult();
Toast.makeText(mContext, "Permission Granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
}

Handle ActivityResultLauncher callback

        ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// Handle the result here

try {
progressBar.setVisibility(View.VISIBLE);
ivCamera.setVisibility(View.GONE);

// TODO : START THE MAIN FUNCTIONALITY

// now call the function createImage() and pass the uri object (line no. 100-110)
geoTagImage.createImage(fileUri);

// set all the customizations for geotagging as per your requirements.
geoTagImage.setTextSize(30f);
geoTagImage.setBackgroundRadius(5f);
geoTagImage.setBackgroundColor(Color.parseColor("#66000000"));
geoTagImage.setTextColor(android.R.color.white);
geoTagImage.setAuthorName("Ashish");
geoTagImage.showAuthorName(true);
geoTagImage.showAppName(true);
geoTagImage.setImageQuality(ImageQuality.LOW);
geoTagImage.setImageExtension(PNG);

// after geotagged photo is created, get the new image path by using getImagePath() method
gtiImageStoragePath = geoTagImage.getImagePath();

/* The time it takes for a Canvas to draw items on a blank Bitmap can vary depending on several factors,
* such as the complexity of the items being drawn, the size of the Bitmap, and the processing power of the device.*/
new Handler().postDelayed(this::previewCapturedImage, 3000);


} catch (GTIException e) {
e.printStackTrace();
}
}
});

Preview the original image

        // preview of the original image
private void previewCapturedImage() {
try {
ivCamera.setVisibility(View.GONE);
Bitmap bitmap = GTIUtility.optimizeBitmap(imageStoragePath);
ivImage.setImageBitmap(bitmap);

if (ivImage.getDrawable() != null) {
ivClose.setVisibility(View.VISIBLE);
}
ivClose.setOnClickListener(v -> {
ivImage.setImageBitmap(null);
ivCamera.setVisibility(View.VISIBLE);
ivClose.setVisibility(View.GONE);
ivImage.setImageDrawable(null);

});

} catch (Exception e) {
e.printStackTrace();
}
}

Handle callback listener methods

@Override
public void onPermissionGranted() {
openCamera();
}
@Override
public void onPermissionDenied() {
GTIPermissions.requestCameraLocationPermission(mContext, PERMISSION_REQUEST_CODE);
}

I hope you like it, Kindly Clapp 👏🏻 this post and give star to this repo on Github. if you have any query or suggestion kindly ping me. Your feedbacks are appreciated.

Follow on : Github, LinkedIn, Instagram

Subscribe on youtube : CodeByAshish

Project Link : GeoTagImage@github

--

--

Ashish Dangi

Android Application Developer, Blogger, App & Web Modifier.