Wednesday 25 February 2015

Android:How to create a Camera apps in Eclipse

1. Android Camera

Most Android devices have at least one camera. Some devices have a front and a back facing camera.
Using the camera on the Android device can be done via the integration of existing camera application. In this case you would start the existing Camera application via an intent and use the return data of the application to access the result.
Alternatively you can also directly integrate the camera into your application via the Camera API.
The following description contains examples for both use cases.

2. Android Basics

The following description assumes that you have already basic knowledge in Android development.
Please check the Android development tutorial to learn the basics. Also see Android development tutorials for more information about Android development.

3. Tutorial: Using an Intent to make a photo

Create a new Android project de.vogella.android.imagepick with an activity called ImagePickActivity.
Adjust the layout of the activity to contain an ImageView with the result ID. Also add a button with the onClick property pointing to a onClick method.
Change the ImagePickActivity class to the following.
package de.vogella.android.imagepick;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class ImagePickActivity extends Activity {
  private static final int REQUEST_CODE = 1;
  private Bitmap bitmap;
  private ImageView imageView;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    imageView = (ImageView) findViewById(R.id.result);
  }

  public void onClick(View View) {
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    startActivityForResult(intent, REQUEST_CODE);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    InputStream stream = null;
    if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
      try {
        // recyle unused bitmaps
        if (bitmap != null) {
          bitmap.recycle();
        }
        stream = getContentResolver().openInputStream(data.getData());
        bitmap = BitmapFactory.decodeStream(stream);

        imageView.setImageBitmap(bitmap);
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } finally ch (IOException e) {
        e{
        if (stream != null)
          try {
            stream.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
      }
  }
} 

4. Tutorial: Using the camera API

In this tutorial you create application which allows you to make a photo via the front camera and to save it on the SD card.

Tip


If you using the Android emulator ensure that you configured the camera and that you added an SD card during the creation of the your Android virtual device.
Create a new Android project called de.vogella.camera.api with an activity called MakePhotoActivity .
Add the android.permission.CAMERA permission to access your camera and the android.permission.WRITE_EXTERNAL_STORAGEto be able to write to the SD card to your AndroidManifest.xml file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.vogella.cameara.api"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="de.vogella.camera.api.MakePhotoActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest> 
Change the main.xml file in the res/layout folder to the following
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/captureFront"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="onClick"
        android:text="Make Photo" />

</RelativeLayout> 
Create the following PhotoHandler class which will be responsible for saving the photo the SD card.
package de.vogella.camera.api;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

public class PhotoHandler implements PictureCallback {

  private final Context context;

  public PhotoHandler(Context context) {
    this.context = context;
  }

  @Override
  public void onPictureTaken(byte[] data, Camera camera) {

    File pictureFileDir = getDir();

    if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

      Log.d(MakePhotoActivity.DEBUG_TAG, "Can't create directory to save image.");
      Toast.makeText(context, "Can't create directory to save image.",
          Toast.LENGTH_LONG).show();
      return;

    }

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
    String date = dateFormat.format(new Date());
    String photoFile = "Picture_" + date + ".jpg";

    String filename = pictureFileDir.getPath() + File.separator + photoFile;

    File pictureFile = new File(filename);

    try {
      FileOutputStream fos = new FileOutputStream(pictureFile);
      fos.write(data);
      fos.close();
      Toast.makeText(context, "New Image saved:" + photoFile,
          Toast.LENGTH_LONG).show();
    } catch (Exception error) {
      Log.d(MakePhotoActivity.DEBUG_TAG, "File" + filename + "not saved: "
          + error.getMessage());
      Toast.makeText(context, "Image could not be saved.",
          Toast.LENGTH_LONG).show();
    }
  }

  private File getDir() {
    File sdDir = Environment
      .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return new File(sdDir, "CameraAPIDemo");
  }
} 
Change the MakePhotoActivity class to the following. This class assumes that you have a button in your layout with the onClickproperty pointing to a onClick() method.
package de.vogella.camera.api;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import de.vogella.cameara.api.R;

public class MakePhotoActivity extends Activity {
  private final static String DEBUG_TAG = "MakePhotoActivity";
  private Camera camera;
  private int cameraId = 0;

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

    // do we have a camera?
    if (!getPackageManager()
        .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
      Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
          .show();
    } else {
      cameraId = findFrontFacingCamera();
      if (cameraId < 0) {
        Toast.makeText(this, "No front facing camera found.",
            Toast.LENGTH_LONG).show();
      } else {
        camera = Camera.open(cameraId);
      }
    }
  }

  public void onClick(View view) {
    camera.takePicture(null, null,
        new PhotoHandler(getApplicationContext()));
  }

  private int findFrontFacingCamera() {
    int cameraId = -1;
    // Search for the front facing camera
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numberOfCameras; i++) {
      CameraInfo info = new CameraInfo();
      Camera.getCameraInfo(i, info);
      if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
        Log.d(DEBUG_TAG, "Camera found");
        cameraId = i;
        break;
      }
    }
    return cameraId;
  }

  @Override
  protected void onPause() {
    if (camera != null) {
      camera.release();
      camera = null;
    }
    super.onPause();
  }

} 
Lastly Enjoy!!!

Android: listview Working with Styles and Themes

1. Styles and Themes

1.1. Styles

Android allow you to define the look and feel, for example colors and fonts, of Android components in XML resource files. This way you have to set common style attributes only once in one central place.
If the entry in the resource file is used to style a view, it is typically referred to as a style, while if it is used for styling an activity or application it is typically called a theme /.
To define a style or a theme, save an XML file in the /res/values directory of your project. The root node of the XML file must be <resources> and you use a style tag that includes the name attribute. This tag contains than more or more item tags which define values for named attributes.
The following styles.xml XML file is an example for a style definition.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="text">
        <item name="android:padding">4dip</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
        <item name="android:textColor">#000000</item>
    </style>
    
    <style name="layout">
        <item name="android:background">#C0C0C0</item>
    </style>
</resources> 
You assign the style attribute to your elements, for example to the text elements via style=”@style/text.

1.2. Inheritance

Styles (and themes) support inheritance by using the parent attribute of the style tag. This way the style inherits all settings from the parent style and can overwrite selected attributes.

1.3. Referring attributes in the current theme

Android lists all standard attributes which can be styled in the R.attr file. The reference for this file can be found online under the following URL: R.attr.
You can refer to individual attributes of the current Android theme via the ?android:attr notation. This notation means that you are referring to a style attribute in the currently active theme.
For example ?android:attr/listPreferredItemHeight means: "use the value defined by the attribute called listPreferredItemHeight in the current theme.
The following layout defines buttons with the Android 4.0 button style.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        style="?android:attr/buttonBarStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/Button01"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Show" />

        <Button
            android:id="@+id/Button02"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Change" />
    </LinearLayout>

    <EditText
        android:id="@+id/myView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" >

        <requestFocus />
    </EditText>

</LinearLayout> 
Screenshot of the running application with the menu open

1.4. Themes

A theme is a style applied to an entire activity or application, rather than an individual View (as in the example above). The technique of defining a theme is the same as defining a style.
The next example show how to define your own theme while extending a platform theme.

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

    <style name="MyTheme" parent="android:Theme.Light">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@color/translucent_red</item>
        <item name="android:listViewStyle">@style/MyListView</item>
    </style>

    <style name="MyListView" parent="@android:style/Widget.ListView">
        <item name="android:listSelector">@drawable/ic_menu_home</item>
    </style>

</resources> 

2. Using Android platform themes

2.1. When and how to use the holo design

As of API 14 and before API 21 the holo design can be used.
  • @android:style/Theme.Holo
  • @android:style/Theme.Holo.Light
  • @android:style/Theme.Holo.Light.DarkActionBar

2.2. When and how to use material design

As of API 21 the material design is the new default design you should be used.
  • @android:style/Theme.Material (dark version)
  • @android:style/Theme.Material.Light (light version)
  • @android:style/Theme.Material.Light.DarkActionBar
The v7 Support Libraries provide themes with material design styles for some widgets. This allows you to use material design on earlier releases. See Maintaining Compatibility for how to use the new theme in earlier releases.

2.3. Styling the color palette

As of material design you can customize the themes base colors. The following screenshot shows several of these colors..
Customize the Color Palette
The following listing is an example of styling it with different colors (defined in your /res/values folder).
<resources>
  <style name="AppTheme" parent="android:Theme.Material">
    <!-- Main theme colors -->
    <!--   your app branding color for the app bar -->
    <item name="android:colorPrimary">@color/primary</item>
    <!--   darker variant for the status bar and contextual app bars -->
    <item name="android:colorPrimaryDark">@color/primary_dark</item>
    <!--   theme UI controls like checkboxes and text fields -->
    <item name="android:colorAccent">@color/accent</item>
  </style>
</resources> 
You can also style the status bar with the android:statusBarColor attribute. By default, android:statusBarColor inherits the value of android:colorPrimaryDark.

2.4. Styling individual views and view groups

As of Android 5.0 (API 21) you can also assign the android:theme for a view. This allows to change the theme for this element and its child elements.

2.5. Best practice for selecting themes

It is considered best practice to inherit the default platform style (the natural style)and to customize it. It is called natural style as this style feels natural to the users on this platform. Users which are used to Android 2.x applications on their phone are usually not happy if you offer your application in a completely different style like holo.
You typically use resource-qualifiers to define which platform them you inherit.
Inherit as of v14 the android:Theme.Holo.Light.DarkActionBar style, as of v11 android:Theme.Holo.Light andandroid:Theme.Light for older versions.

Android: Live WallPaper Tutorial

Table of Contents1. Pre-requisitions2. Overview2.1. Live Wallpapers2.2. How to create a live wallpaper2.3. Intent to set the wallpaper3. Android Wallpaper Example4. About this website4.1. Donate to support free tutorials4.2. Questions and discussion4.3. License for this tutorial and its code5. Links and Literature5.1. Source Code5.2. Android Resources5.3. vogella Resources





1. Pre-requisitions

The following tutorial assumes that you have already basic knowledge in Android development. Please check the Android development tutorial to learn the basics.

2. Overview

2.1. Live Wallpapers

Live Wallpapers are animated, interactive backgrounds for the Android home screen. A live wallpaper is similar to other Android applications and can use most of the same functionality.

2.2. How to create a live wallpaper

To create a live wallpaper, you need to create an XML file which describes your wallpaper. This file should contain a description of the application and can contain a preview and a link to a preference activity Activity which allow to customize the live wallpaper.
You also create a service which must extend the WallpaperService class. This class is the base class for all live wallpapers in the system. You must implement the onCreateEngine() method and return an object of typeandroid.service.wallpaper.WallpaperService.Engine. This objects handles the lifecycle events, animations and drawings of the wallpaper. The Engine class defines the life cycle methods, as for example onCreate()onSurfaceCreated(),onVisibilityChanged()onOffsetsChanged()onTouchEvent() and onCommand().
The service requires the permission android.permission.BIND_WALLPAPER and must be registered via an intent-filter for theandroid.service.wallpaper.WallpaperService action.
You should also enter in the AndroidManifest.xml file of the application that your application uses theandroid.software.live_wallpaper feature. This will prevent that your wallpaper can be installed on devices which do not support live wallpapers.

2.3. Intent to set the wallpaper

You can use an Intent to set the Wallpaper.

// Button to set the Wallpaper
public void onClick(View view) {
  Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
  intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
    new ComponentName(this, MyWallpaperService.class));
  startActivity(intent);
} 

3. Android Wallpaper Example

Create a new project called de.vogella.android.wallpaper. Do not create an activity.
Create the /res/xml folder and create the mywallpaper.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:thumbnail="@drawable/icon"
  android:description="@string/wallpaper_description"  
  android:settingsActivity="de.vogella.android.wallpaper.MyPreferencesActivity"/> 
This file contains a description of your wallpaper and a preview graphic. You can also enter a link to an activity which allow to configure the wallpaper. This resource file will be linked to from the AndroidManifest.xml. You could also include the "android:thumbnail attribute" which would point to a drawable which gives a smaller image of the running wallpaper.
Change your AndroidManifest.xml to the following to define your MyWallpaperService service. Also define the uses-feature.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.vogella.android.wallpaper"
    android:versionCode="1"
    android:versionName="1.0" >

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <service
            android:name="MyWallpaperService"
            android:enabled="true"
            android:label="Wallpaper Example "
            android:permission="android.permission.BIND_WALLPAPER" >
            <intent-filter>
                <action android:name="android.service.wallpaper.WallpaperService" >
                </action>
            </intent-filter>

            <meta-data
                android:name="android.service.wallpaper"
                android:resource="@xml/mywallpaper" >
            </meta-data>
        </service>

        <activity
            android:name=".MyPreferencesActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.Light.WallpaperSettings" >
        </activity>
        <activity
            android:name=".SetWallpaperActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.Light.WallpaperSettings" >
            <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.software.live_wallpaper"
        android:required="true" >
    </uses-feature>

</manifest> 
We create the MyPoint class to save the elements we have drawn.
package de.vogella.android.wallpaper;

public class MyPoint {
  String text;
  private int x;
  private int y;

  public MyPoint(String text, int x, int y) {
    this.text = text;
    this.x = x;
    this.y = y;
  }
} 
Create a new activity. Create the prefs.xml preference file in the res/xml folder.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
  <CheckBoxPreference android:key="touch"
    android:title="Enable Touch"></CheckBoxPreference>
  <EditTextPreference android:key="numberOfCircles"
    android:title="Number of Circles"></EditTextPreference>
</PreferenceScreen> 
Create a new activity called MyPreferencesActivity and the following class.
package de.vogella.android.wallpaper;

import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.widget.Toast;

public class MyPreferencesActivity extends PreferenceActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);

    // add a validator to the "numberofCircles" preference so that it only
    // accepts numbers
    Preference circlePreference = getPreferenceScreen().findPreference("numberOfCircles");

    // add the validator
    circlePreference.setOnPreferenceChangeListener(numberCheckListener);
  }

  
/** * Checks that a preference is a valid numerical value */
Preference.OnPreferenceChangeListener numberCheckListener = new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { // check that the string is an integer if (newValue != null && newValue.toString().length() > 0 && newValue.toString().matches("\\d*")) { return true; } // If now create a message to the user Toast.makeText(MyPreferencesActivity.this, "Invalid Input", Toast.LENGTH_SHORT).show(); return false; } }; }
Create the following coding for the Wallpaper service.
package de.vogella.android.wallpaper;

import java.util.ArrayList;
import java.util.List;

import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class MyWallpaperService extends WallpaperService {

  @Override
  public Engine onCreateEngine() {
    return new MyWallpaperEngine();
  }

  private class MyWallpaperEngine extends Engine {
    private final Handler handler = new Handler();
    private final Runnable drawRunner = new Runnable() {
      @Override
      public void run() {
        draw();
      }

    };
    private List<MyPoint> circles;
    private Paint paint = new Paint();
    private int width;
    int height;
    private boolean visible = true;
    private int maxNumber;
    private boolean touchEnabled;

    public MyWallpaperEngine() {
      SharedPreferences prefs = PreferenceManager
          .getDefaultSharedPreferences(MyWallpaperService.this);
      maxNumber = Integer
          .valueOf(prefs.getString("numberOfCircles", "4"));
      touchEnabled = prefs.getBoolean("touch", false);
      circles = new ArrayList<MyPoint>();
      paint.setAntiAlias(true);
      paint.setColor(Color.WHITE);
      paint.setStyle(Paint.Style.STROKE);
      paint.setStrokeJoin(Paint.Join.ROUND);
      paint.setStrokeWidth(10f);
      handler.post(drawRunner);
    }

    @Override
    public void onVisibilityChanged(boolean visible) {
      this.visible = visible;
      if (visible) {
        handler.post(drawRunner);
      } else {
        handler.removeCallbacks(drawRunner);
      }
    }

    

} 
@Override
    public void onSurfaceDestroyed(SurfaceHolder holder) {
      super.onSurfaceDestroyed(holder);
      this.visible = false;
      handler.removeCallbacks(drawRunner);
    }

    @Override
    public void onSurfaceChanged(SurfaceHolder holder, int format,
        int width, int height) {
      this.width = width;
      this.height = height;
      super.onSurfaceChanged(holder, format, width, height);
    }

    @Override
    public void onTouchEvent(MotionEvent event) {
      if (touchEnabled) {

        float x = event.getX();
        float y = event.getY();
        SurfaceHolder holder = getSurfaceHolder();
        Canvas canvas = null;
        try {
          canvas = holder.lockCanvas();
          if (canvas != null) {
            canvas.drawColor(Color.BLACK);
            circles.clear();
            circles.add(new MyPoint(String.valueOf(circles.size() + 1), x, y));
            drawCircles(canvas, circles);

          }
        } finally {
          if (canvas != null)
            holder.unlockCanvasAndPost(canvas);
        }
        super.onTouchEvent(event);
      }
    }

    private void draw() {
      SurfaceHolder holder = getSurfaceHolder();
      Canvas canvas = null;
      try {
        canvas = holder.lockCanvas();
        if (canvas != null) {
          if (circles.size() >= maxNumber) {
            circles.clear();
          }
          int x = (int) (width * Math.random());
          int y = (int) (height * Math.random());
          circles.add(new MyPoint(String.valueOf(circles.size() + 1),
              x, y));
          drawCircles(canvas, circles);
        }
      } finally {
        if (canvas != null)
          holder.unlockCanvasAndPost(canvas);
      }
      handler.removeCallbacks(drawRunner);
      if (visible) {
        handler.postDelayed(drawRunner, 5000);
      }
    }

    // Surface view requires that all elements are drawn completely
    private void drawCircles(Canvas canvas, List<MyPoint> circles) {
      canvas.drawColor(Color.BLACK);
      for (MyPoint point : circles) {
        canvas.drawCircle(point.x, point.y, 20.0f, paint);
      }
    }
  } 
Create the following Activity which should use a layout with one Button included. This Button should use the onClick property to point to the onClick method.
package de.vogella.android.wallpaper;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class SetWallpaperActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }

  public void onClick(View view) {
    Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
    intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
        new ComponentName(this, MyWallpaperService.class));
    startActivity(intent);
  }
} 


Live Wallpaper displayed