开发者

Camera Preview and GPS reading in Android

开发者 https://www.devze.com 2023-03-12 21:18 出处:网络
I tried to write an android app. For now I wrote some code that display camera prewiew and gets data from sensors on the device (gps reciver).

I tried to write an android app. For now I wrote some code that display camera prewiew and gets data from sensors on the device (gps reciver).

When I run the code in separate app (like camera preview as one app and application that gets gps data as a second) everything is OK. But when I try to integrate this two modules - GPS stop working; it looks like the listener doesn't get any data and moreover as i am trying it on the emulator so for that reason i have initialized the latitude and longitude with a value so that in case a location is not recieved it does not give null.

The app should function in a way that as soon as the photograph is clicked and saved to the sdcard ,at the very same time i should get the gps location of the device which would also be needed to save on the sd card.Did You had some similar problems?

The code looks like this:

public class MainActivity extends Activity implements CameraCallback{
private FrameLayout cameraholder = null;
private CameraSurface camerasurface = null;
LocationManager mLocationManager;
LocationListener mlocListener;
Double lat;
Double lng;

/* Class My Location Listener */
public class MyLocationListener implements LocationListener
{
        public void onLocationChanged(Location loc)
        {
                String Text = "My current location is:\n" + "Latitude = " + loc.getLatitude() + "\nLongitude = " + loc.getLongitude()+ "\nAccuracy = "+ loc.getAccuracy();
                Toast.makeText(MainActivity.this,Text,Toast.LENGTH_SHORT).show();
        }

        public void onProviderDisabled(String provider)
        {
                Toast.makeText(MainActivity.this,"Gps Disabled",Toast.LENGTH_SHORT ).show();
        }

        public void onProviderEnabled(String provider)
        {
                /*Toast.makeText(getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show();*/
                Toast.makeText(MainActivity.this,"Gps Enabled",Toast.LENGTH_SHORT).show();
        }

        public void onStatusChanged(String provider, int status, Bundle extras){}
        {
                Toast.makeText(MainActivity.this, "Provider status changed",Toast.LENGTH_LONG).show();  
        }
}


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    cameraholder = (FrameLayout)findViewById(R.id.camera_preview);

    mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    mlocListener = new MyLocationListener();
    mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);

    setupPictureMode();

    ((ImageButton)findViewById(R.id.takepicture)).setOnClickListener(onButtonClick);
    ((ImageButton)findViewById(R.id.about)).setOnClickListener(onButtonClick);
}

private void setupPictureMode(){
    camerasurface = new CameraSurface(this);

    cameraholder.addView(camerasurface, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

    camerasurface.setCallback(this);
}

@Override
public void onJpegPictureTaken(byte[] data, Camera camera) {
    try
    {
        long currentTime = System.currentTimeMillis();
        FileOutputStream outStream = new FileOutputStream(String.format(
                "/sdcard/%d.jpg",currentTime));

        outStream.write(data);
        outStream.close();

        //mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        /*mlocListener = new MyLocationListener();
        mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);*/
        Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        if (location == null) {
            lat = 13.6972 * 1E6;
            lng = 100.5150 * 1E6;
        } else { // get real location if can retrieve the location sent by DDMS or GPS
            lat = location.getLatitude() * 1E6;
            lng = location.getLongitude() * 1E6;
        }

        //GeoPoint point = new GeoPoint(lat.intValue(), lng.intValue());
        System.out.println("Latitude is :"+lat+" Logitude is "+lng);
        mLocationManager.removeUpdates(mlocListener);
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        camerasurface.startPreview();
    }

}

The cameraPreview code looks like:

public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback, OnGestureListener{    
private Camera camera = null;
private SurfaceHolder holder = null;
private CameraCallback callback = null;
private GestureDetector gesturedetector = null;

public Cam开发者_如何学CeraSurface(Context context, AttributeSet attrs, int defStyle) 
{
    super(context, attrs, defStyle);
    initialize(context);
}
public CameraSurface(Context context) 
{
    super(context);
    initialize(context);
}
public CameraSurface(Context context, AttributeSet attrs) 
{
    super(context, attrs);
    initialize(context);
}

private void initialize(Context context) 
{
    holder = getHolder();

    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    gesturedetector = new GestureDetector(this);
}

public void setCallback(CameraCallback callback){
    this.callback = callback;
}

public void startPreview(){
    camera.startPreview();
}

public void startTakePicture(){
    camera.autoFocus(new AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            takePicture();
        }
    });
}

public void takePicture() {
    camera.takePicture(
            new ShutterCallback() {
                @Override
                public void onShutter(){
                    if(null != callback) callback.onShutter();
                }
            },
            new PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera){
                    if(null != callback) callback.onRawPictureTaken(data, camera);
                }
            },
            new PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera){
                    if(null != callback) callback.onJpegPictureTaken(data, camera);
                }
            });
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
    if(null != camera)
    {
        camera.startPreview();
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    camera = Camera.open();

    try {
        camera.setPreviewDisplay(holder);
        camera.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                if(null != callback) callback.onPreviewFrame(data, camera);
            }
        });
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopPreview();
    camera.release();

    camera = null;
}}

The manifest file looks this way:

<?xml version="1.0" encoding="utf-8"?>

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name="com.varma.samples.camera.ui.MainActivity"
              android:label="@string/app_name"
              android:screenOrientation="landscape"
              android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

<uses-sdk android:minSdkVersion="10" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Any help would be appreciated..


Correct me if I'm wrong but you are explicitly stopping location updates the first time you click a picture

 mLocationManager.removeUpdates(mlocListener);

in the callback onJpegPictureTaken()

Also getLastKnownLocation() will give the last cached location, not the latest one. You require the single shot mode.

Even more info: You can enable some setting in your camera with which the picture is geotagged with the lat-lon. Instead of getting the lat-lon yourself read the Jpeg metadata.


As per my understanding what you want is Camera application which produces geotagged(lat/long written) jpeg image. Here is the code for how you can achive it.

Permission needed in AndroidManifest.xml are

 <uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />

<uses-permission android:name="android.permission.CAMERA" >
</uses-permission>

Here is Activity file

public class TaggedImageActivity extends Activity implements SurfaceHolder.Callback, OnClickListener{

static final int FOTO_MODE = 0;
private LocationManager locationManager;
private SurfaceView surefaceView;
private SurfaceHolder surefaceHolder;
private LocationListener locationListener;
private Camera camera;
private String make;
private String model;
private String imei;
private Location thislocation;  
double lat  ;
double lon ;

private boolean previewRunning = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFormat(PixelFormat.TRANSLUCENT);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.main);
    surefaceView = (SurfaceView) findViewById(R.id.surface_camera);
    surefaceView.setOnClickListener(this);
    surefaceHolder = surefaceView.getHolder();
    surefaceHolder.addCallback(this);
    surefaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    locationListener = new LocationListener() {

            public void onStatusChanged(String provider, int status, Bundle extras) {

            }

            public void onProviderEnabled(String provider) {

            }

            public void onProviderDisabled(String provider) {

            }

            public void onLocationChanged(Location location) {

                 TaggedImageActivity.this.gpsLocationReceived(location);
                lat = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getLatitude();
                lon = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getLongitude();
            }
        };




        locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        Criteria locationCritera = new Criteria();
        locationCritera.setAccuracy(Criteria.ACCURACY_COARSE);
        locationCritera.setAltitudeRequired(false);
        locationCritera.setBearingRequired(false);
        locationCritera.setCostAllowed(true);
        locationCritera.setPowerRequirement(Criteria.NO_REQUIREMENT);
        String providerName = locationManager.getBestProvider(locationCritera, true);

        if (providerName != null && locationManager.isProviderEnabled(providerName)) {
           locationManager.requestLocationUpdates(providerName, 20000, 100, TaggedImageActivity.this.locationListener);
        } else {
            // Provider not enabled, prompt user to enable it
            Toast.makeText(TaggedImageActivity.this, R.string.please_turn_on_gps, Toast.LENGTH_LONG).show();
            Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            TaggedImageActivity.this.startActivity(myIntent);
        }

        if(locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)!=null){

                  lat = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER).getLatitude();
        lon = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER).getLongitude();
        }



        else if (locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)!=null){
            Log.d("TAG", "Inside NETWORK");

             lat = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getLatitude();
            lon = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getLongitude();

        }

        else{

            Log.d("TAG", "else +++++++ ");
            lat = -1;
            lon = -1;
        }

}

protected void gpsLocationReceived(Location location) {

    thislocation = location;
}

AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){

    @Override
    public void onAutoFocus(boolean arg0, Camera arg1) {
        Toast.makeText(getApplicationContext(), "'It is ready to take the photograph !!!", Toast.LENGTH_SHORT).show();
    }};
 Camera.PictureCallback pictureCallBack = new Camera.PictureCallback() {

        public void onPictureTaken(byte[] data, Camera camera) {
                if(data != null){
                    Intent imgIntent = new Intent();
                    storeByteImage(data);
                    camera.startPreview();
                    setResult(FOTO_MODE, imgIntent);
                }

            }
        };
      public boolean storeByteImage(byte[] data){

            String filename = Environment.getExternalStorageDirectory()+String.format("/%d.jpeg", System.currentTimeMillis());
            Log.d("TAG", "filename = "+ filename);

            try {
                FileOutputStream fileOutputStream = new FileOutputStream(filename);
                try {
                    fileOutputStream.write(data);
                    Log.d("TAG", "Image file created, size in bytes = "+ data.length);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                fileOutputStream.flush();
                fileOutputStream.close();

                Log.e("TAG", "lat ="+ lat+"  lon :"+ lon);
                ExifInterface exif = new ExifInterface(filename);
                createExifData(exif,lat , lon);
                exif.saveAttributes();

                Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null,null);
            while (cursor.moveToNext()) {
                String imagefilename = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                Long latitide = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.LATITUDE));
                Long longitude = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.LONGITUDE));

                Log.d("TAG", "filepath: "+imagefilename+" latitude = "+latitide+"  longitude = "+longitude);
            }

            return true;

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        }

        public void createExifData(ExifInterface exif, double lattude, double longitude){

                    if (lattude < 0) {
                exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "S");
                lattude = -lattude;
            } else {
                exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "N");
            }

            exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE,
                    formatLatLongString(lattude));

            if (longitude < 0) {
                exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "W");
                longitude = -longitude;
            } else {
                exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "E");
            }
            exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE,
                    formatLatLongString(longitude));

            try {
                exif.saveAttributes();
            } catch (IOException e) {

                e.printStackTrace();
            }
            make = android.os.Build.MANUFACTURER; // get the make of the device
            model = android.os.Build.MODEL; // get the model of the divice

            exif.setAttribute(ExifInterface.TAG_MAKE, make);
            TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
            imei = telephonyManager.getDeviceId();
            exif.setAttribute(ExifInterface.TAG_MODEL, model+" - "+imei);

            exif.setAttribute(ExifInterface.TAG_DATETIME, (new Date(System.currentTimeMillis())).toString()); // set the date & time

            Log.d("TAG", "Information : lat ="+ lattude+"  lon ="+ longitude+"  make = "+make+"  model ="+ model+"  imei="+imei+" time ="+(new Date(System.currentTimeMillis())).toString());
       }

        private static String formatLatLongString(double d) {
            StringBuilder b = new StringBuilder();
            b.append((int) d);
            b.append("/1,");
            d = (d - (int) d) * 60;
            b.append((int) d);
            b.append("/1,");
            d = (d - (int) d) * 60000;
            b.append((int) d);
            b.append("/1000");
            return b.toString();
          }


        protected boolean isRouteDisplayed() {
            return false;
        }


@Override
public void onClick(View v) {

    camera.takePicture(null, pictureCallBack, pictureCallBack);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {

    camera = Camera.open();

}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
        if(previewRunning){
        camera.stopPreview();
    }

    try {
        camera.setPreviewDisplay(holder);
    } catch (IOException e) {
        e.printStackTrace();
    }
    camera.startPreview();
    previewRunning = true;
    }

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopPreview();
    previewRunning = false;
    camera.release();   

}

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.cameramenu, menu);
    return true;
}

public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) {
        case R.id.item01:    
             Toast.makeText(this, "Pressed !", Toast.LENGTH_LONG).show();           break;
        case R.id.item03:     
             System.exit(0);            
             break;
    }
    return true;
}


@Override
protected void onStop() {
    super.onStop();
    LocationManager locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
    locationManager.removeUpdates(this.locationListener);
}}
0

精彩评论

暂无评论...
验证码 换一张
取 消