如何从 Android Studio 中的 ImageView 中提取 GPS 坐标

问题描述 投票:0回答:1

我有一个 Android 应用程序,我想在其中显示 ImageView 的 GPS 坐标,这是我从用户上传的图像中获得的。我的代码如下所示:

package com.example.app;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import androidx.exifinterface.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.lang.Rational;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.GpsDirectory;
import com.example.java_lib.client.Client;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity implements LocationListener {

    private static final String TAG = "MainActivity";
    private static final int REQUEST_LOCATION_PERMISSION = 1;

    Button uploadButton, cameraButton, analyzeButton;
    TextView result;
    ImageView image;
    Bitmap bitmap;
    double[] gpsCoordinates = null;

    private LocationManager locationManager;

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

        askForPermission();

        Spinner spinner = findViewById(R.id.spinner_drop);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this,
                R.array.LMMs,
                android.R.layout.simple_spinner_item
        );
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        uploadButton = findViewById(R.id.uploadButton);
        cameraButton = findViewById(R.id.cameraButton);
        analyzeButton = findViewById(R.id.analyzeButton);
        result = findViewById(R.id.result);
        image = findViewById(R.id.imageView2);

        uploadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*");
                startActivityForResult(intent, 1);
            }
        });

        cameraButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
                } else {
                    getLocationAndCaptureImage();
                }
            }
        });

        analyzeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (bitmap != null) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            sendImageAndCoordinatesToServer(bitmap, gpsCoordinates);
                        }
                    }).start();
                } else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "No image available. Please select or capture an image first.", Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        });

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    }

    private void getLocationAndCaptureImage() {
        try {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(intent, 2);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onLocationChanged(@NonNull Location location) {
        gpsCoordinates = new double[]{location.getLatitude(), location.getLongitude()};
        locationManager.removeUpdates(this);
    }

    void askForPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
                    checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION}, 2);
            }
        }
    }

    @SuppressLint("MissingSuperCall")
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 2) {
            if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                this.askForPermission();
            }
        } else if (requestCode == REQUEST_LOCATION_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getLocationAndCaptureImage();
            } else {
                Toast.makeText(this, "Location permission is required to capture GPS data", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
            Uri uri = data.getData();
            result.setText(uri.toString());
            try {
                bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
                image.setImageBitmap(bitmap);

                // Speichern Sie das Bitmap in einer Datei
                File savedImageFile = saveBitmapToFile(bitmap);
                if (savedImageFile != null) {
                    String filePath = savedImageFile.getAbsolutePath();
                    gpsCoordinates = extractGPSData(filePath);
                    result.setText("Latitude: " + gpsCoordinates[0] + ", Longitude: " + gpsCoordinates[1]);
                } else {
                    result.setText("Failed to save image.");
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else if (requestCode == 2 && resultCode == RESULT_OK && data != null) {
            bitmap = (Bitmap) data.getExtras().get("data");
            image.setImageBitmap(bitmap);

            // Speichern Sie das Bitmap in einer Datei
            File savedImageFile = saveBitmapToFile(bitmap);
            if (savedImageFile != null) {
                String filePath = savedImageFile.getAbsolutePath();
                try {
                    gpsCoordinates = extractGPSData(filePath);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                result.setText("Latitude: " + gpsCoordinates[0] + ", Longitude: " + gpsCoordinates[1]);
            } else {
                result.setText("Failed to save image.");
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }




    private double[] extractGPSData(String filePath) throws IOException {
        File imageFile = new File(filePath);
        Metadata metadata = null;
        try {
            metadata = ImageMetadataReader.readMetadata(imageFile);
        } catch (ImageProcessingException e) {
            throw new RuntimeException(e);
        }

        // Log all metadata for debugging purposes
        for (com.drew.metadata.Directory directory : metadata.getDirectories()) {
            for (com.drew.metadata.Tag tag : directory.getTags()) {
                Log.d("Metadata", directory.getName() + " - " + tag.getTagName() + " - " + tag.getDescription());
            }
        }

        GpsDirectory gpsDirectory = metadata.getFirstDirectoryOfType(GpsDirectory.class);
        double[] gpsCoordinates = new double[2];

        if (gpsDirectory != null) {
            Rational[] latitudes = gpsDirectory.getRationalArray(GpsDirectory.TAG_LATITUDE);
            Rational[] longitudes = gpsDirectory.getRationalArray(GpsDirectory.TAG_LONGITUDE);
            String latRef = gpsDirectory.getString(GpsDirectory.TAG_LATITUDE_REF);
            String lonRef = gpsDirectory.getString(GpsDirectory.TAG_LONGITUDE_REF);

            Log.d("GPS Data", "Latitudes: " + Arrays.toString(latitudes));
            Log.d("GPS Data", "Longitudes: " + Arrays.toString(longitudes));
            Log.d("GPS Data", "Latitude Ref: " + latRef);
            Log.d("GPS Data", "Longitude Ref: " + lonRef);

            if (latitudes != null && longitudes != null && latRef != null && lonRef != null) {
                double latitude = convertToDegree(latitudes);
                if (latRef.equals("S")) {
                    latitude = -latitude;
                }
                double longitude = convertToDegree(longitudes);
                if (lonRef.equals("W")) {
                    longitude = -longitude;
                }
                gpsCoordinates[0] = latitude;
                gpsCoordinates[1] = longitude;
                Log.d("GPS Data", "Latitude: " + latitude + ", Longitude: " + longitude);
            } else {
                Log.d("GPS Data", "GPS data not found or incomplete.");
                result.setText("No GPS data found.");
            }
        } else {
            Log.d("GPS Data", "GPS directory not found.");
            result.setText("No GPS data found.");
        }

        return gpsCoordinates;
    }



    private double convertToDegree(Rational[] rationalArray) {
        double degrees = rationalArray[0].doubleValue();
        double minutes = rationalArray[1].doubleValue();
        double seconds = rationalArray[2].doubleValue();
        return degrees + (minutes / 60.0) + (seconds / 3600.0);
    }



    private double[] extractGPSDataFromBitmap(Bitmap bitmap) throws IOException {
        File file = new File(getExternalFilesDir(null), "temp_image.jpg");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        }
        return extractGPSData(String.valueOf(Uri.fromFile(file)));
    }

    private void sendImageAndCoordinatesToServer(Bitmap bitmap, double[] gpsCoordinates) {
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
            byte[] imageBytes = byteArrayOutputStream.toByteArray();
           // new Client(imageBytes, gpsCoordinates).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getFilePathFromUri(Uri uri) {
        String filePath = null;
        try {
            InputStream inputStream = getContentResolver().openInputStream(uri);
            File tempFile = createTempFileFrom(inputStream);
            filePath = tempFile.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filePath;
    }

    private File createTempFileFrom(InputStream inputStream) throws IOException {
        File tempFile = File.createTempFile("temp_image", ".jpg", getCacheDir());
        tempFile.deleteOnExit();
        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    }

    private File saveBitmapToFile(Bitmap bitmap) {
        File tempFile = null;
        try {
            tempFile = File.createTempFile("temp_image", ".jpg", getCacheDir());
            tempFile.deleteOnExit();
            FileOutputStream out = new FileOutputStream(tempFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return tempFile;
    }


}

我现在遇到的问题是,“extractGPSData(String filePath)”函数不会返回 GPS 坐标,因为如果您查看上传图像的 logcats 元数据,您会发现,图片是0.0。这是我这边的问题吗?或者我如何提取上传图像的 GPS 坐标。非常感谢!

我尝试了目前提取GPS坐标的方法。我还尝试从另一个 stackoverflow 帖子中获取纬度和经度:

ExifInterface exif = new ExifInterface(filepath);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);

我有点困惑。

java android imageview android-gps
1个回答
0
投票

这是我这边的问题吗

是的。您需要使用原始图像。相反,您正在通过

saveBitmapToFile()
方法制作浪费的副本。然后你尝试使用该副本。除其他问题外,副本没有 EXIF 标头。

所以,首先删除

saveBitmapToFile()

我还尝试从另一个 stackoverflow 帖子中获取纬度和经度

这种方法与您所能得到的一样好,但是您需要使用与 ExifInterface()

 一起使用的 
InputStream
,来自
androidx.exifinterface:exifinterface
库:

ExifInterface exif = new ExifInterface(getContentResolver().openInputStream(uri));
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);

请注意,任何图像都不需要具有 GPS EXIF 标头。

© www.soinside.com 2019 - 2024. All rights reserved.