[Sony Cross-Device General] Geeks Empire:
Tutorial to Start Programming for Xperia Camera Add-On

2. Starting...

- Create New Android Project (Alt + Shift + N)

* Minimum Requirement: API 16

* Target: API 19/20

* Compile with: Sony Add-on SDK 3.0 (API-19)

Note:You can Add Xperia Camera Add-On support to your current custom camera Application by Adding few elements to your app.

- from Bottom to Top

​

* Open Manifest & Add require Permissions for using Add-On API, Camera Hardware & Storage.

The Storage permission is for create file in SD-Card for capture pics and Camera to get permission from system to allow us to use Camera hardware.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="com.sonymobile.permission.CAMERA_ADDON"/>

- Declare required library inside Application in manifest

<!-- If you want to create a camera app for just Xperia device you should set[B] required="true"[/B]. False means your can be install on other devices-->
<uses-library android:name="com.sonymobile.camera.addon.api" android:required="false"/>

- Then you will have your Activities declaration. You should add specific Intent-Filter & Meta-Data for the Activities that you want show on Camera Add-On menu. In this sample I set it for main activity.

<activity
android:name=".BasicCameraApp"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:launchMode="singleTask" >
<!-- The widowSoftInputMode is preferred to use But
launchMode="singleTask" must be set because there is another apps in Add-On menu that can launch or
switch between different modes -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="com.sonymobile.camera.addon.action.REGISTER_MODE" />
</intent-filter>
<meta-data android:name="com.sonymobile.camera.addon.MODE_ATTRIBUTES"
android:resource="@xml/sample_mode" />
<!-- This XML file save all required attributes for Info show in add-on menu and etc-->
</activity>

* Under res/ create xml folder & then .xml file to generate required meta-data

res/xml/sample_mode.xml

<?xml version="1.0" encoding="utf-8"?>
<modes xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Do Not hard-code your won't register as add-on -->
<mode
<!-- [B]Remember [/B]the name="" because you need this to use it in classes cause this name will register
If you set incorrect your mode won't be available in modes menu -->
name="cameraw"
descriptionLabel="@string/app_name"
selectorIcon="@drawable/mode_icon"
shortcutIcon="@drawable/mode_shortcut_icon"
selectorLabel="@string/app_name"
shortcutLabel="@string/app_name" >
<uses-feature android:name="android.hardware.camera" />
</mode>
</modes>

* In layout folder you should add element for Preview of Camera. You can use TextureView, SurfaceView & FrameLayout. In this basic sample there is SurfaceView.

* In drawable you should add file for icon & shortcut of your add-on that must follow the guidelines. For better understand I upload the Xperia Camera drawable resources + what you can check in Sample Code drawable.

* Now Coding...

import com.sonymobile.camera.addon.capturingmode.CapturingModeSelector;

First you should define as specific parameter of Camera Add-On API

/**This class opens and closes the capturing mode selector. The mode selector provides access to all registered camera modes for camera add-ons available to the user. All methods must be called from the UI thread. **/
CapturingModeSelector mCapturingModeSelector;

- Then you need to define two listener for Selecting process & while closing the modes menu;

public static final String MODE_NAME = "cameraw";

private class MyOnModeSelectListener implements CapturingModeSelector.OnModeSelectListener {
Override
public void onModeSelect(String modeName) {
if (mCapturingModeSelector != null) {
mCapturingModeSelector.close();
mModeSelectorButton.setVisibility(View.VISIBLE);
}
}
}

private class MyOnModeFinishListener implements CapturingModeSelector.OnModeFinishListener {
Override
public void onModeFinish() {
if (mCapturingModeSelector != null) {
mCapturingModeSelector.close();
}
finish();
}
}

- The Handle the Click & Touch on Mode Button

private class ModeSelectorButtonTouchListener implements View.OnTouchListener {
Override
public boolean onTouch(View v, MotionEvent event) {
mModeSelectorButton.onTouchEvent(event);
if (mModeSelectorButton.isPressed()) {
mModeSelectorButton.setColorFilter(PRESSED_COLOR_FILTER);
} else {
mModeSelectorButton.clearColorFilter();
}
return true;
}
}

private class ModeSelectorButtonClickListener implements View.OnClickListener {
Override
public void onClick(View v) {
if (mCapturingModeSelector != null) {
[B]// This is name attributes in .xml file as meta-data[/B]
mCapturingModeSelector.open(MODE_NAME);
mModeSelectorButton.setVisibility(View.INVISIBLE);
mModeSelectorButton.clearColorFilter();
}
}
}

- Then at Override onCreate you should define them;

mModeSelectorButton.setOnClickListener(new ModeSelectorButtonClickListener());
mModeSelectorButton.setOnTouchListener(new ModeSelectorButtonTouchListener());

- & on @override onResume these. onResume for these to handle their action when user back to your app that she didn't close it completely so she need modes selector to switch modes;

mCapturingModeSelector.setOnModeSelectListener(new MyOnModeSelectListener());
mCapturingModeSelector.setOnModeFinishListener(new MyOnModeFinishListener());

NOTE: These are mandatory in your Activity that want to support add-on.

If you have already Camera App you should add what previously said up to here and you done!

It means these are common elements that you should add for Camera Add-On support.

^^^

^^^

*** Sample Codes ***

​

* How to Capture By Proximity Sensor?

I.

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

II. implements you activity from SensorEventListener

public class BasicCameraApp extends Activity implements SensorEventListener{}

III. Override onCreate(Bundle Saved){} you must declare instance of Sensor & SensorManager

//define [COLOR=Blue][B]sensorManager [/B][/COLOR]& declare which sensor do you want to use
//that here is [COLOR=Blue][B]Proximity_SENSOR[/B][/COLOR]
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

Then you need to register the sensor to get data from it at Override onResume(){} cause this must be available for user when back to your app.

mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_FASTEST);

Now you have interaction with proximity sensor so we need to capture function and integrate it with sensorEvent.

Note: Always Unregister Sensors when user leave your app. It means you should release the camera, and all other sensor you are using in your app

Override
public void onPause(){
super.onPause();

mSensorManager.unregisterListener(this);
mCameraWrapper.mCamera.release();
}

IV. Then define PictureCallback to handle received data from Camera Lens and write them to File.

private PictureCallback mPicture = new PictureCallback() {
Override
public void onPictureTaken(byte[] data, Camera camera) {
//Here you will have array of data from camera and save these data to file as picture
// there is almost always separate function to handle name files and extension
// and here just write byte[] data to that file
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);

// NOTE: Handle the image rotation after saving the file.
try {
// [B]pictureFile[/B] that created in [B]getOutputMediaFile()[/B] function now set to FileOutputStream
FileOutputStream fos = new FileOutputStream(pictureFile);
//here bye[] data write in created file.
fos.write(data);
fos.close();

Toast.makeText(getApplicationContext(), "Captured", Toast.LENGTH_SHORT).show();
}
catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
}
catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
finally {
//start camera preview after file created and data wrote in it.
mCameraWrapper.mCamera.startPreview();
}
}
};

public static final int MEDIA_TYPE_IMAGE = 1;
private File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "AddOn_GeeksEmpire");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("CameraW", "failed to create directory");
return null;
}
}

// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
//this is empty jpg image file with timestamp to prevent overwrite
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "AddON_"+ timeStamp + ".jpg");
}
else {
return null;
}

return mediaFile;
}

>> After this we just need to call takePicture() function to take a pic...

V. When you implements the activity from SensorEventListener it will ask you to add unimplemented methods, that will be these two function at least.

Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { }

Override
public void onSensorChanged(SensorEvent event) {
//Proximity Sensor detect near interaction ~5cm
//in this case of sensor type system have one
float p = event.values[0];
System.out.println("Proximity >> " + p);

if(p == 0){
//here i call takePicture function when value of Sensor (destination) be 0
// like tap on sensor or hover nearly
mCameraWrapper.mCamera.takePicture(null, null, mPicture);
}
}

There should be also a Class that handle the surfaceView for preview of Camera Because It is easy to understand and not any special point in this simple example I just wrote detail inside the CameraWraper.class

Just few code...

- You define Camera parameter & then use Open(int id) function to launch camera & after this use startPreview() function to see live view through camera lens.

So First you need to add Preview (SurfaceView) & then use Camera.

In this sample...

SurfaceView surfaceView = (SurfaceView)findViewById(R.id.surface);
CameraWrapper mCameraWrapper = new CameraWrapper(); //class that handle the preview
surfaceView.getHolder().addCallback(mCameraWrapper);

Camera mCamera;
try{
mCamera.open(); /*Or you can use open(int id) the id can define the front & back camera. usually if you don't set id it will launch back camera (int id = 0)*/
} catch (RuntimeException e) {
// here is good point to handle errors if there is problem with Camera maybe from other app or System.
} finally{
mCamera.startPreview();
}

Note: You can use these inside camera preview class or directly in activity class.

Note: When there is change in surfaceView, change the orientation for instance, first you should stop the live view, apply new configuration and then startPreview().

Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}

// set preview size and make any resize, rotate or
// reformatting changes here
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

} catch (Exception e){
//
}
}

End of Proximity Capture |

OOOOOOO

The explanations of codes are available inside each classes.

Don't forget to Hit Thanks
​