GeoTagImage

GeoTagImage is an open-source Android SDK for GPS-based photo tagging, used in survey apps, property inspection, delivery tracking and GIS systems.

Why choose GTI?

πŸ“

Precision Geotagging

Captures Real-time Latitude, Longitude, and Altitude with high-accuracy GPS providers.

πŸ—ΊοΈ

Dynamic Map Snapshots

Automatically fetches and embeds a Google Map preview of the current location onto the photo.

🏠

Reverse Geocoding

Converts coordinates into human-readable addresses (City, State, Country) automatically.

πŸ“Έ

CameraX Integration

Built on Google's modern CameraX API for smooth hardware abstraction and stability.

🎨

Design Customization

Modify font family, text size, color, and background transparency to match your branding.

⚑

Lightweight & Fast

Optimized image processing ensures minimal lag between capture and saving.

πŸ”

Smart Permissions

Handles complex Android 13+ location and camera permission flows out of the box.

πŸ“…

Timestamping

Embed localized date and time stamps in multiple formats directly into the image pixels.

πŸ› οΈ

Flexible Output

Choose between URI, File, or Bitmap outputs depending on your app's requirements.

πŸš€

Kotlin & Java

Full support for both languages with idiomatic extensions for Kotlin users.

Advanced Capabilities

🧭

Accuracy Control

Select GPS priority, update intervals, and accuracy thresholds for enterprise-grade surveys.

🧱

Offline Ready

Location caching ensures image tagging works even without internet connectivity.

🧩

Modular Design

Use only what you need: camera, location, overlays, or metadata injection.

πŸ”

Lifecycle Safe

Automatically handles Activity & Fragment lifecycle changes without memory leaks.

πŸ“‚

Scoped Storage

Fully compatible with Android 10+ scoped storage and MediaStore guidelines.

πŸ§ͺ

Test-Friendly

Clean APIs allow mocking of location and camera for unit and UI testing.

Ideal Use Cases

πŸ—οΈ Field Surveys

Capture proof-based images for land, utility, and infrastructure surveys.

🏠 Property Inspection

Attach verified location data to real-estate and housing inspections.

πŸš“ Compliance & Audits

Ensure location authenticity for compliance, audits, and verification apps.

πŸ›΅ Delivery Proof

Log timestamped, geotagged delivery images with zero manual effort.

Quick Setup


dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven( url = "https://jitpack.io")
    }
}
dependencies {
    implementation "com.github.dangiashish:GeoTagImage:1.2.3"
}

<!-- Add inside application tag -->
<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>

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

class MainActivity : AppCompatActivity(), PermissionCallback {

    private var gtiUri: Uri? = null
    private lateinit var geoTagImage: GeoTagImage
    private lateinit var cameraLauncher: ActivityResultLauncher<Uri>
    private lateinit var permissionLauncher: ActivityResultLauncher<Array<String>>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
    }
}

permissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
    val allGranted = permissions.all { it.value }
    if (allGranted) onPermissionGranted()
    else onPermissionDenied()
}

cameraLauncher =
    registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
        if (success) {
            gtiUri = geoTagImage.processCapturedImage()
            previewCapturedImage()
        }
    }

geoTagImage = GeoTagImage(this, permissionLauncher, cameraLauncher)
geoTagImage.requestCameraAndLocationPermissions()

binding.ivCamera.setOnClickListener {
    geoTagImage.launchCamera(
        onImageCaptured = { uri ->
            gtiUri = uri
            previewCapturedImage()
        },
        onFailure = {
            Toast.makeText(mContext, it, Toast.LENGTH_SHORT).show()
        }
    )
}

geoTagImage.setTextSize(30f)
geoTagImage.setBackgroundRadius(5f)
geoTagImage.setBackgroundColor(Color.parseColor("#66000000"))
geoTagImage.setTextColor(Color.WHITE)
geoTagImage.setAuthorName("Ashish")
geoTagImage.showAuthorName(true)
geoTagImage.showAppName(true)
geoTagImage.setLabel("Clicked By")
geoTagImage.setCameraAspectRatio(GeoTagImage.Ratio_4X3)

private fun previewCapturedImage() {
    gtiUri?.let { uri ->
        val bitmap =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
                ImageDecoder.decodeBitmap(ImageDecoder.createSource(contentResolver, uri))
            else
                MediaStore.Images.Media.getBitmap(contentResolver, uri)

        binding.ivImage.setImageBitmap(bitmap)
    }
}

override fun onPermissionGranted() {
}

override fun onPermissionDenied() {
    geoTagImage.requestCameraAndLocationPermissions()
}
// Kotlin Usage
val geoTagImage = GeoTagImage(context, permissionLauncher, cameraLauncher)

geoTagImage.launchCamera(
    onImageCaptured = { uri ->
        // Logic after image is tagged
    },
    onFailure = { exception ->
        Log.e("GTI", exception.message.toString())
    }
)
The Mind Behind GTI

About the Author

Ashish Dangi

Ashish Dangi

Android Engineer & SDK Architect

The creator of GeoTagImage (GTI). With deep expertise in GIS and survey systems, Ashish specializes in building robust, field-ready Android architectures that bridge the gap between complex geospatial data and intuitive user experiences.