Geotags on Images in Android Studio (GeoTagImage)
Published: 2023-08-02 03:00:34

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 :**
- Request camera & location permission callback by itself.
- Show location and address.
- Show Lat Longs.
- Show author name.
- Show app name.
- Show Google map snapshot.
- Set Image Quality.

**Handle Visibilities :**
- Show/hide app name — `showAppName()`
- Show/hide author name — `showAuthoraName()`
- Show/hide google map — `showGoogleMap()`
- Show/hide Lat Longs — `showLatLng()`

So lets start, the brief summary of these points :

- 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()`.

- Show Location & Address — The library can draw device’s current 
location such as sub-admin area, locality and country name along with complete address.

- Show Lat Longs — The library can also draw device’s current 
coordinates such as latitude and longitude.

- 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**.

- 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)`.

- 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.
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.

**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.0.7'
}
```
**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 onActivityResult method**

```
// override the onActivityResult method
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // check the request code for the result
        if (requestCode == CAMERA_IMAGE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {

                // if result is OK then preview the original created image file.
                previewCapturedImage();

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

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

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


                } catch (GTIException e) {
                    throw new RuntimeException(e);
                }


                // handle the error or cancel events
            } else if (resultCode == RESULT_CANCELED) {
                Toast.makeText(mContext, "Cancelled image capture", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(mContext, "Sorry! Failed to capture image", Toast.LENGTH_SHORT).show();
            }
        }
    }
```

**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 Like ❤️ this post and give star to this repo on [Github](https://github.com/dangiashish/GeoTagImage). if you have any query or suggestion kindly ping me. Your feedbacks are appreciated.

Follow on : [Github](https://github.com/dangiashish), [LinkedIn](https://linkedin.com/in/ashishkumardangi), [Instagram](https://instagram.com/coder.ashish)
Subscribe on youtube : [CodeByAshish](https://youtube.com/CodeByAshish)
Project Link : [GeoTagImage@github](https://github.com/dangiashish/GeoTagImage)