askIT

Android Flashlight tutorial

This tutorial shows you how to create a simple application for Android. It will turn on and off the flashlight on your cell phone.

save.png Download source code for flashlight

01 Create project

Start up Android Studio and select New Project. Click next to the project is created.

01_nytt_prosjekt.jpg

01_nytt_prosjekt.jpg

Benytt API 21 (Android 5.0). This is the minimum to run the flashlight.

03_nytt_prosjektb.jpg

Select Empty Activity.

04_add_an_activity_to_mobile.jpg

05_customize_the_activity.jpg

02 Start emulator

Start up the emulator by clicking on 07_run.jpg Run app. You should then see a blank application.

08_lunch_emulator.jpg.

09_ny_tom_app.jpg.

03 Design

We are now going to design the flashlight. First download images for on and off.
Save the images to the folder:

C:\Users\bruker\AndroidStudioProjects\Lommelykt\app\src\main\res\drawable

flashlight_off.png
flashlight_off.png

flashlight_on.png
flashlight_on.png

Go to the file activity_main:
app -> res > layout > activity_main.xml

10_activity_main_xml.jpg

Drag and drop a ToggleButton and ImageView to the design.

11_togglebutton_imageview.jpg
Figure: Drag and drop ToggleButton and ImageView.

11_designer_theme.jpg
Figure: You can change the theme of the torch by clicking Theme (this is optional).

Use the designer to place the text at the top, flashlight icon in the middle and switch on the bottom. Change the text from "Hello World" to "Flashlight is off". Change the picture to the flashlight.

12_designer.jpg
Figure: Drag the items so you can get text to the top, image at center and switch on the bottom.

If you are having problems then you can go to the XML view by clicking on "Text". Copy and paste from activity_main.xml below.
12_text.jpg.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.nettport.flashlight.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Flashlight is off"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textAppearance="@style/TextAppearance.AppCompat.Large" />

    <ToggleButton
        android:text="ToggleButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/toggleButton"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@drawable/flashlight_off"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/imageView" />
</RelativeLayout>

04 MainActivity appearance and button

We will look at the appearance of the app. The flashlight starts in off mode, and it is important that the design reflects this. When you click the button, the text and icon will change.

13_off.png 13_on.png

Go to MainActivity.java

To find on-off button in the design, we use the Java code "findViewById". We create a variable named "onOffButton" and assign the button:
    ToggleButton onOffButton = (ToggleButton) findViewById(R.id.toggleButton);

If you get a red text for ToggleButton then you need to import the libary. Hit Alt+Enter and select Import class:

import_class_togglebutton.jpg

Then we create a listener on the button. If the button is clicked, an operation is performed.
onOffButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    }
});

If you get a red text for View then you need to import the libary. Hit Alt+Enter and select Import class:

import_class_view.jpg

We will create a code to check if ToggleButton is enabled or not. We will do this inside the listner. If ToggeButton is enabled we will change the text and icon to 1 (on).
If it is not enabled we will change the text and icon to 0 (off). This is done in the method:
    changeTextAndIcon(0); for off.
    changeTextAndIcon(1); for on.

The method changeTextAndIcon will be created by this code:

void changeTextAndIcon(int modus) {
}

This will change the text and the icon. See full code for MainActivity below.

package com.nettport.flashlight;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;

public class MainActivity extends AppCompatActivity {

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

                // Click button on or off
                ToggleButton onOffButton = (ToggleButton) findViewById(R.id.toggleButton);
                onOffButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                        }
                });
        }


        /*- Change text and icon ------------------------------------- */
        // modus = 1 -> turn on
        // modus = 0 -> turn off
        void changeTextAndIcon(int modus) {
                // Change text
                TextView statusText = (TextView) findViewById(R.id.textView);
                if (modus == 1) {
                        statusText.setText("Flashlight is on"); // Flash is on
                } else {
                        statusText.setText("Flashlight is off"); // Flash is off
                }

                // Change icon to off
                ImageView flashlightIcon = (ImageView) findViewById(R.id.imageView);
                if (modus == 1) {
                        flashlightIcon.setImageResource(R.drawable.flashlight_on);
                } else {
                        flashlightIcon.setImageResource(R.drawable.flashlight_off);
                }
        }
}

05 Android Manifest

The Android app need access to the camera to turn on the flashlight. This is done by writing access code in Android Manifest.

15_androidmanifest.jpg

Open "app -> manifest --> AndroidManifest.xml". Add everything listed under "Allows access to the flashlight"

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.nettport.flashlight">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        >
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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


    <!-- Allows access to the flashlight -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.camera.flash" />


</manifest>

06 Flash

Now we can create the code for the flashlight.

package com.nettport.flashlight;

import android.Manifest;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraMetadata;
import android.util.Size;
import android.view.Surface;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
        CameraManager cameraManager;
        CameraCharacteristics cameraCharacteristics;

        CameraDevice mCameraDevice;
        CameraCaptureSession mSession;

        CaptureRequest.Builder mBuilder;


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

                // Initialize camera
                initCamera();

                // Click button on or off
                ToggleButton onOffButton = (ToggleButton) findViewById(R.id.toggleButton);
                onOffButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                // your click actions go here
                                if (((ToggleButton) v).isChecked()) {
                                        changeTextAndIcon(1);
                                        turnOnFlashLight();
                                } else {
                                        changeTextAndIcon(0);
                                        turnOffFlashLight();
                                }
                        }
                });
        }


        @Override
        public void onPause() {
                super.onPause(); // Always call the superclass method first
                changeTextAndIcon(0);
                turnOffFlashLight();
                close();
        }
        @Override
        public void onResume() {
                super.onResume();
                initCamera();
                changeTextAndIcon(1);
                turnOffFlashLight();
        }

        /*- Change text and icon ------------------------------------- */
        // modus = 1 -> turn on
        // modus = 0 -> turn off
        void changeTextAndIcon(int modus) {
                // Change text
                TextView statusText = (TextView) findViewById(R.id.textView);
                if (modus == 1) {
                        statusText.setText("Flashlight is on"); // Flash is on
                } else {
                        statusText.setText("Flashlight is off"); // Flash is off
                }

                // Change icon to off
                ImageView flashlightIcon = (ImageView) findViewById(R.id.imageView);
                if (modus == 1) {
                        flashlightIcon.setImageResource(R.drawable.flashlight_on);
                } else {
                        flashlightIcon.setImageResource(R.drawable.flashlight_off);
                }
        }
        private void initCamera() {
                cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
                try {
                        String[] id = cameraManager.getCameraIdList();
                        if (id != null && id.length > 0) {
                                cameraCharacteristics = cameraManager.getCameraCharacteristics(id[0]);
                                boolean isFlash = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
                                if (isFlash) {
                                        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                                                // TODO: Consider calling
                                                //                ActivityCompat#requestPermissions
                                                // here to request the missing permissions, and then overriding
                                                // public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                                //                                                                                                                                                                int[] grantResults)
                                                // to handle the case where the user grants the permission. See the documentation
                                                // for ActivityCompat#requestPermissions for more details.
                                                return;
                                        }
                                        cameraManager.openCamera(id[0], new MyCameraDeviceStateCallback(), null);
                                        Toast.makeText(this, "Camera initialized", Toast.LENGTH_LONG).show();
                                }
                        }
                }
                catch (CameraAccessException e)
                {
                        e.printStackTrace();
                        Toast.makeText(this, "Camera initialization error:\n" + e.toString(), Toast.LENGTH_LONG).show();
                }
        }

        class MyCameraDeviceStateCallback extends CameraDevice.StateCallback
        {
                SurfaceTexture mSurfaceTexture = new SurfaceTexture(1);

                @Override
                public void onOpened(CameraDevice camera)
                {
                        mCameraDevice = camera;
                        // get builder
                        try
                        {
                                mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                                List list = new ArrayList();
                                Size size = getSmallestSize(mCameraDevice.getId());
                                mSurfaceTexture.setDefaultBufferSize(size.getWidth(), size.getHeight());
                                Surface mSurface = new Surface(mSurfaceTexture);
                                list.add(mSurface);
                                mBuilder.addTarget(mSurface);
                                camera.createCaptureSession(list, new MyCameraCaptureSessionStateCallback(), null);
                        }
                        catch (CameraAccessException e)
                        {
                                e.printStackTrace();

                        }
                }

                @Override
                public void onDisconnected(CameraDevice camera)
                {

                }

                @Override
                public void onError(CameraDevice camera, int error)
                {

                }
        }

        private Size getSmallestSize(String cameraId) throws CameraAccessException
        {
                Size[] outputSizes = cameraManager.getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(SurfaceTexture.class);
                if (outputSizes == null || outputSizes.length == 0)
                {
                        throw new IllegalStateException("Camera " + cameraId + "doesnt support any outputSize.");
                }
                Size chosen = outputSizes[0];
                for (Size s : outputSizes)
                {
                        if (chosen.getWidth() >= s.getWidth() && chosen.getHeight() >= s.getHeight())
                        {
                                chosen = s;
                        }
                }
                return chosen;
        }
        class MyCameraCaptureSessionStateCallback extends CameraCaptureSession.StateCallback
        {
                @Override
                public void onConfigured(CameraCaptureSession session)
                {
                        mSession = session;
                        try
                        {
                                mSession.setRepeatingRequest(mBuilder.build(), null, null);
                        }
                        catch (CameraAccessException e)
                        {
                                e.printStackTrace();
                        }
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession session)
                {

                }
        }

        public void turnOnFlashLight()
        {
                try
                {
                        mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
                        mSession.setRepeatingRequest(mBuilder.build(), null, null);
                        Toast.makeText(this, "Flash activated", Toast.LENGTH_LONG).show();
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                        Toast.makeText(this, "Flash failed:\n" + e.toString(), Toast.LENGTH_LONG).show();
                }
        }

        public void turnOffFlashLight()
        {
                try
                {
                        mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
                        mSession.setRepeatingRequest(mBuilder.build(), null, null);
                        Toast.makeText(this, "Flash disabled", Toast.LENGTH_LONG).show();
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                        Toast.makeText(this, "Flash failed:\n" + e.toString(), Toast.LENGTH_LONG).show();
                }
        }

        private void close()
        {
                Toast.makeText(this, "Camera closed", Toast.LENGTH_LONG).show();
                if (mCameraDevice == null || mSession == null)
                {
                        return;
                }
                mSession.close();
                mCameraDevice.close();
                mCameraDevice = null;
                mSession = null;
        }
}

07 IC Launcher

The last thing to be done now is to change the icon of the application. The icon consists of five different formats. The path of the icons is "C:\Users\bruker\AndroidStudioProjects\Lommelykt\app\src\main\res". You can either save the icons below in the respective folders, or create your own icons.

16_ic_launcher.jpg

mipmap-mdpi/ic_launcher.png
mipmap-mdpi

mipmap-hdpi/ic_launcher.png
mipmap-hdpi

mipmap-xhdpi/ic_launcher.png
mipmap-xhdpi

mipmap-xxhdpi/ic_launcher.png
mipmap-xxhdpi

mipmap-xxxhdpi/ic_launcher.png
mipmap-xxxhdpi

08 Start application

The application is now complete. Click on Run to start it. Try to test on your mobile phone!

07_run.jpg

Add comment

avatar_blank_60.png

Comment:

Name:

Email:

Comments

No comments yet. You can be the first one to comment. Just write your comment in the form and click on the submit button.