2

I'm trying to develop an application for to turn on the flashlight on click in a toggle. I tried every method I found in the web but without success in my nexus 5. The only application that works is the cyanogenmod torch but even if I take that code and I write it in my application, it creates a notification that if clicked it opens the cyanogenmod torch app and not mine! This is a problem!! Is it possible have a easy code that works also for nexus 5?

public void turnOffFlashLight() {
    try {
        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
            cam.stopPreview();
            cam.release();
            cam = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(getBaseContext(), "Exception throws in turning off flashlight.", Toast.LENGTH_SHORT).show();
    }
}

public void turnOnFlashLight() {
    try {
        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
            cam = Camera.open();
            cam.setPreviewTexture(new SurfaceTexture(0));
            Parameters p = cam.getParameters();
            p.setFlashMode(Parameters.FLASH_MODE_TORCH);

            cam.setParameters(p);
            cam.startPreview();
        }
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(getBaseContext(), "Exception throws in turning on flashlight.", Toast.LENGTH_SHORT).show();
    }
}

EDIT: logcat

04-09 21:52:21.967: E/AndroidRuntime(5346): FATAL EXCEPTION: main
04-09 21:52:21.967: E/AndroidRuntime(5346): Process: com.lob.twixlight, PID: 5346
04-09 21:52:21.967: E/AndroidRuntime(5346): android.util.SuperNotCalledException: Activity {com.lob.twixlight/com.lob.twixlight.MainActivityTwixLight} did not call through to super.onStart()
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.app.Activity.performStart(Activity.java:5243)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2178)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2265)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.app.ActivityThread.access$800(ActivityThread.java:145)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1206)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.os.Handler.dispatchMessage(Handler.java:102)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.os.Looper.loop(Looper.java:136)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at android.app.ActivityThread.main(ActivityThread.java:5081)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at java.lang.reflect.Method.invokeNative(Native Method)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at java.lang.reflect.Method.invoke(Method.java:515)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
04-09 21:52:21.967: E/AndroidRuntime(5346):     at dalvik.system.NativeStart.main(Native Method)

ENTIRE MainActivity

public class MainActivity extends Activity implements Callback  { 


    private ImageView imageView3;
    private ImageButton mButtonOn;
    private Camera cam;
    private SurfaceHolder mHolder ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        new AlertDialog.Builder(this);
        setContentView(R.layout.activity_main);
        mButtonOn = (ImageButton) findViewById(R.id.my_button);
        imageView3 = (ImageView) findViewById(R.id.imageView3);


        SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
        mHolder = preview.getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void info(View v) {
        Intent intent = new Intent(this, FullscreenActivity.class);
        startActivity(intent);
        overridePendingTransition(R.anim.in, R.anim.out);
    }

    protected void onStart() {
        super.onStart ();
        SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
        mHolder = preview.getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        mHolder = holder;

        try {
            Log.i("SurfaceHolder", "setting preview");
            cam.setPreviewDisplay(mHolder);  
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        cam.stopPreview();

        mHolder = null;
    }


}
Atlas91
  • 5,754
  • 17
  • 69
  • 141

1 Answers1

5

Ok, first, make sure you have added the surface view to your xml layout, ABOVE that of your button:

<SurfaceView
    android:id="@+id/PREVIEW"
    android:layout_width="1dp"
    android:layout_height="1dp"/>

//image button comes below

<ImageButton
    android:id="@+id/my_button" /> 

Now, in your java class, implement the SurfaceHolder.Callback interface, for example:

public class MyFlashlight extends Activity implements Callback

this will auto-generate three callback methods:

surfaceChanged();
surfaceCreated();
surfaceDestroyed();

leave that as it is for now. In your onStart(); method, add the following:

SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
SurfaceHolder mHolder = preview.getHolder();
mHolder.addCallback(this);

do not add this to onCreate(); as it(onCreate();) is only called once and it will cause issues if the activity is to be restarted.

In your turnOnFlash(); method, do the usual:

//get parameters
//set parameters
//set flashmode
//start preview

In your surfaceCreated(); method, add this:

mHolder = holder;
        try {
            Log.i("SurfaceHolder", "setting preview");
            camera.setPreviewDisplay(mHolder);  
        } catch (IOException e){
            e.printStackTrace();
        }

In your surfaceDestroyed(); method, stop the preview:

camera.stopPreview();
mHolder = null;

Leave surfaceChanged(); empty

Thats it!!!! Give it a try!!!

Here is a full working example:

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MyFlashLight extends Activity implements Callback{

//flag to detect flash is on or off
private boolean isLighOn = false;

private Camera camera;

private Button button;

    @Override
protected void onStart() {
    super.onStart();

         SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
                SurfaceHolder mHolder = preview.getHolder();
                mHolder.addCallback(this);
    }
}

@Override
protected void onStop() {
    super.onStop();

    if (camera != null) {
        camera.release();
    }
}

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

    button = (Button) findViewById(R.id.buttonFlashlight);

    Context context = this;
    PackageManager pm = context.getPackageManager();

    // if device support camera?
    if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        Log.e("err", "Device has no camera!");
        return;
    }

    camera = Camera.open();
    final Parameters p = camera.getParameters();

    button.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) {

            if (isLighOn) {
                                turnOffFlash();
            } else {
                                turnOnFlash();
                          }
                     }
    });


            private void turnOnFlash(){
            Log.i("info", "torch is turn on!");

                p.setFlashMode(Parameters.FLASH_MODE_TORCH);

                camera.setParameters(p);
                camera.startPreview();
                isLighOn = true;

            }
            private void turnOffFlash(){
            Log.i("info", "torch is turn off!");

                p.setFlashMode(Parameters.FLASH_MODE_OFF);
                camera.setParameters(p);
                camera.stopPreview();
                isLighOn = false;
    @Override
    public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder){
        mHolder = holder;
        try {
            Log.i("SurfaceHolder", "setting preview");
            camera.setPreviewDisplay(mHolder);  
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder){
        Log.i("SurfaceHolder", "stopping preview");
        camera.stopPreview();
        mHolder = null;
    }

}

}

  • Am on the road,, when i get home(about 4 hours)i will give you some sample code – SuperStallion Apr 08 '14 at 12:08
  • can you post the example you told me yesterday please?:) – Atlas91 Apr 09 '14 at 15:49
  • Well, check out my app "premium flashlight™" on the playstore and let me know:) – SuperStallion Apr 09 '14 at 18:21
  • Two things: I really need to create this app..so if you use hangout can you getting in touch with me there please? And second can you directly give me the link of your application? Because I find too many torch apps ah ah :-) – Atlas91 Apr 09 '14 at 18:24
  • Works perfectly!! I sent you an email :-) – Atlas91 Apr 09 '14 at 19:04
  • Got your email. add me to your circles on g+. Remember, if my above code works for you, accept it so it can help others also – SuperStallion Apr 09 '14 at 19:11
  • What I still do not understand is why the SurfaceView has to be placed ABOVE the Button. Any particular reason for doing that? – jap1968 Sep 10 '14 at 21:46
  • @jap1968 it doesn't matter where surface view is, it just hold there to hide it! – Amir Hossein Ghasemi Sep 20 '14 at 07:49
  • 1
    I'm not sure if you are allowed to use the TradeMark sign like that. I doubt that you hold the trademark "Flashlight". Anyway thanks for your solution. But a little explaination would be great. I.e. why the other methods do not work on the Nexus 5. Does the surface view have to be visible? – Stefan Fabian Sep 28 '14 at 12:17
  • It worked for me thanks, but anyone who can give a bit explanation , why we need to include surfaceholder??why without it, code doesnt works – Nicks Oct 20 '14 at 00:08
  • is the code complete? beacuse i guess u would need to import import android.view.SurfaceView; import android.view.SurfaceHolder; – huzefam Oct 26 '14 at 16:36
  • do you have a github link for the above code for reference? – huzefam Oct 26 '14 at 16:42
  • hey dude ..refactored it and it worked..will post on githib soon! thanks a ton – huzefam Oct 26 '14 at 16:51
  • @jap1968 surface view is no longer required (somewhat), you can use SurfaceTexture instead.....much simpler to implement – SuperStallion Jan 03 '15 at 13:38