How to take photos of Android background service

Source: Internet
Author: User

First, Background introduction

Recently encountered a requirement in the project. Implement a background photo-taking function.

Start looking for solutions on the Internet. Also tried a lot of ways to achieve, there is no comfortable solution. Just make sure the difficulty: that is, to preview the photo before calling the camera method. The problem also comes along. Since the background is to take pictures, you want to be in the service or an asynchronous thread, which is a bit contradictory to previewing this step.

What can you do to preview, take pictures, and not be aware of the user? Presumably you will also think of a trickery approach: Hide the Preview interface.

To illustrate, this is just a solution that I think of in my groping. Can be very good to solve the business needs.

For photos like the "Find Phone" feature offered by very many phone manufacturers. I'm not sure how they are implemented. Let's say we have a better approach. It's better to have a conversation.

The question of whether this feature infringes the privacy of the user, the security of the user, etc. is beyond our consideration and discussion.

Ii. Introduction of the programme

The scenario implementation steps are generally as follows:

1. Initialize the preview screen (core part) of the camera; 2. Get camera cameras when you need to take a photo, and set a preview screen for the camera; 3. Open the preview. Finished taking pictures. Release camera resources (important) 4. Save, rotate, upload ... (by business decision)

First of all, about the business requirements: from the user login to logoff this period of time, received background photos of the instructions after the photo, save, upload.

The implementation of each step is described in detail below based on this business scenario.

1. Initialize the photo preview screenin the test process, it was found that the preview interface of the photo should be generated in the case of display, ability to take a normal photo, if it is directly created Surfaceview instance as a preview interface. Then the direct call to take the picture throws an exception to the native layer: take_failed. Think of the source code to look for solutions to the problem. Discover the function code of the core of the camera is above the native layer, so put aside. Assume that the preview interface must be displayed at the top level when taking a photo.

Because the app either in the foreground or the home back to the desktop, the need to meet this condition, the preview interface should be global, very easy to associate with a global form to use as a vector of the preview interface.

If this global form is not visible. does not affect the normal interaction of the subsequent interface. So. I thought of using the global context to get the WindowManager object to manage this global form.

Then look directly at the code:

Package Com.yuexunit.zjjk.service;import Com.yuexunit.zjjk.util.logger;import Android.content.context;import Android.view.surfaceview;import Android.view.windowmanager;import android.view.windowmanager.layoutparams;/** * Hides the global form. For background Photography * * @author wurs */public class Camerawindow {private static final String TAG = CameraWindow.class.getSimpleName () ;p rivate static WindowManager windowmanager;private static Context applicationcontext;private static Surfaceview dummycameraview;/** * Show Global form * * @param context */public static void Show (context context) {if (ApplicationContext = = nul L) {applicationcontext = Context.getapplicationcontext (); WindowManager = (WindowManager) Applicationcontext.getsystemservice (context.window_service);d Ummycameraview = new Surfaceview (applicationContext) ; Layoutparams params = new Layoutparams ();p arams.width = 1;params.height = 1;params.alpha = 0;params.type = LayoutParams.TY pe_system_alert;//Shielded Click event Params.flags = layoutparams.flag_not_touch_modal| Layoutparams.flag_not_focusable| Layoutparams.flag_not_touchable;windowmanager.addview (Dummycameraview, params); LOGGER.D (tag, tag + "showing");}} /** * @return Get Form view */public static Surfaceview Getdummycameraview () {return dummycameraview;} /** * Hidden form */public static void dismiss () {try {if (WindowManager! = NULL && Dummycameraview! = null) {Windowmanag Er.removeview (Dummycameraview); LOGGER.D (tag, tag + "dismissed");}} catch (Exception e) {e.printstacktrace ();}}}


The code is very easy. The main function is to display the form, get the Surfaceview for previewing, and close the form.

in this business, the show method can be called directly in the application class of its own definition. Such After the app launches, the form is there, only in the app destroy (note that the end of all activity does not close, because it initializes in application, its lifetime is applied, unless the active call to the dismiss method actively shuts down). finished initializing the preview interface. The whole implementation is actually very easy.

Perhaps a lot of people have the problem is that the card in the absence of a preview screen how to take photos here, I hope such a trickery way to help you in future projects encountered can not directly solve the problem. Be able to consider from another angle to solve this problem.

2. Complete Service photo functionThe above-mentioned steps will be merged here.

First on the code:

Package Com.yuexunit.zjjk.service;import Java.io.file;import Java.io.filenotfoundexception;import Java.io.fileoutputstream;import Java.io.ioexception;import Android.app.service;import android.content.Intent; Import Android.graphics.bitmap;import Android.graphics.bitmapfactory;import Android.graphics.bitmapfactory.options;import Android.hardware.camera;import Android.hardware.Camera.CameraInfo; Import Android.hardware.camera.picturecallback;import Android.os.ibinder;import Android.os.message;import Android.text.textutils;import Android.view.surfaceview;import Com.yuexunit.sortnetwork.android4task.UiHandler; Import Com.yuexunit.sortnetwork.task.taskstatus;import Com.yuexunit.zjjk.network.requesthttp;import Com.yuexunit.zjjk.util.filepathutil;import Com.yuexunit.zjjk.util.imagecompressutil;import Com.yuexunit.zjjk.util.logger;import com.yuexunit.zjjk.util.wakelockmanager;/** * Background photo service. Use the global form with * * @author wurs */public class Cameraservice extends Service implements Picturecallback {private STatic final String TAG = CameraService.class.getSimpleName ();p rivate Camera mcamera;private boolean isrunning; Whether the private String CommandId has been photographed in the surveillance; Directive id@overridepublic void OnCreate () {LOGGER.D (TAG, "onCreate ..."); Super.oncreate ();} @Overridepublic int Onstartcommand (Intent Intent, int flags, int startid) {wakelockmanager.acquire (this); LOGGER.D (TAG, "Onstartcommand ..."); Starttakepic (intent); return start_not_sticky;} private void Starttakepic (Intent Intent) {if (!isrunning) {commandId = Intent.getstringextra ("CommandId"); Surfaceview preview = Camerawindow.getdummycameraview (); if (! Textutils.isempty (commandId) && preview! = null) {autotakepic (preview);} else {stopself ();}}} private void Autotakepic (Surfaceview preview) {LOGGER.D (TAG, "autotakepic ..."); isrunning = True;mcamera = Getfacingfrontcamera (); if (Mcamera = = null) {LOGGER.W (TAG, "Getfacingfrontcamera return null"); Stopself (); return;} try {mcamera.setpreviewdisplay (Preview.getholder ()); Mcamera.startpreview ()//Start preview//Prevent some phonesThe photo taken is not bright enough thread.sleep ($); Takepicture ();} catch (Exception e) {e.printstacktrace (); Releasecamera (); Stopself ();}} private void Takepicture () throws Exception {LOGGER.D (TAG, "takepicture ..."); try {mcamera.takepicture (null, NULL, this) ;} catch (Exception e) {logger.d (TAG, "Takepicture failed!"); E.printstacktrace (); throw e;}} Private Camera Getfacingfrontcamera () {camerainfo camerainfo = new Camerainfo (); int numberofcameras = Camera.getnumberofcameras (); for (int i = 0; i < Numberofcameras; i++) {Camera.getcamerainfo (I, camerainfo); if (Camerai nfo.facing = = Camerainfo.camera_facing_front) {try {return camera.open (i)} catch (Exception e) {e.printstacktrace ();}}} return null;} @Overridepublic void Onpicturetaken (byte[] data, camera camera) {LOGGER.D (TAG, "Onpicturetaken ..."); Releasecamera (); try {//greater than 500K, compression prevents memory overflow options opts = null;if (data.length > * 1024x768) {opts = new Options (); opts.insamplesize = 2;} Bitmap Bitmap = bitmapfactory.decodebytearray (data, 0, data.length,opts);//rotate 270-degree biTMap Newbitmap = Imagecompressutil.rotatebitmap (bitmap, 270);//save string fullfilename = Filepathutil.getmonitorpicpath () + system.currenttimemillis () + ". jpeg"; File saveFile = Imagecompressutil.convertbmptofile (newbitmap,fullfilename); Imagecompressutil.recylebitmap ( NEWBITMAP); if (saveFile! = null) {//uploads requesthttp.uploadmonitorpic (CallbackHandler, commandid,savefile);} else {// Save failed. Close stopself ();}} catch (Exception e) {e.printstacktrace (); Stopself ();}}  Private Uihandler CallbackHandler = new Uihandler () {@Overridepublic void Receivermessage (Message msg) {switch (MSG.ARG1) {Case TaskStatus.LISTENNERTIMEOUT:case TaskStatus.ERROR:case taskstatus.finished://request ended, close service stopself (); break;}}};/ /Save Photo Private Boolean savepic (byte[] data, File savefile) {FileOutputStream fos = null;try {fos = new FileOutputStream (sav efile); fos.write (data); Fos.flush (); Fos.close (); return true;} catch (FileNotFoundException e) {e.printstacktrace ();} catch (IOException e) {e.printstacktrace ();} finally {if (Fos! = Nu ll{try {fos.close ();} catch (IOException e) {e.printstacktrace ();}}} return false;} private void Releasecamera () {if (Mcamera! = null) {LOGGER.D (TAG, "Releasecamera ..."); Mcamera.stoppreview (); Mcamera.release (); mcamera = null;}} @Overridepublic void OnDestroy () {Super.ondestroy (); LOGGER.D (TAG, "OnDestroy ..."); commandId = Null;isrunning = false; Filepathutil.deletemonitoruploadfiles (); Releasecamera (); Wakelockmanager.release ();} @Overridepublic ibinder onbind (Intent Intent) {return null;}}
There is not much code. There are just a few points that need special attention,1. The camera is not available during the call. Or another application that does not have the camera when it is held, the camera needs to be captured. The exception for Open (). Prevents an error from being applied when the camera is not acquired. 2. When testing with Huawei camera. Start the preview to take photos immediately, found that the photo is very low brightness, the reason is only the test, detailed need to check the information. So the workaround is to let the thread hibernate 200ms before calling the camera.

3. If you do not use the camera resources or any anomalies, please remember to release the camera resources, otherwise the camera is always held, other applications include the system of the camera can not be used, only to restart the phone solution.

Code everyone can optimize under. The non-normal business logic is handled uniformly. Or is. Use your own defined Uncaughtexceptionhandler to handle uncaught exceptions.

4. With regard to the Wakelocamanager class in the code, it is the wake-up lock management class that I encapsulated, which is one of the special concerns that you need to focus on when dealing with your back-office business, ensuring that business logic is being processed. The system does not enter hibernation. When the business logic is processed. Release the wake-up lock to put the system into hibernation.

Iii. SummaryThe problem of the program is also much more, just to provide a way of thinking. A global form is the core of this approach. Camera operation needs to be cautious, the acquisition of the time required to catch the exception (native exception, connection camera error. I believe you have also encountered), do not use or abnormal when released in a timely manner (the camera object can be written as static, and then in the global anomaly capture in the release of the camera, to prevent the camera during the time of the application of the exception caused by the camera is abnormal hold). Otherwise, other camera applications will not be available.

code you can use a little change, remember to join the relevant permissions. The following are the system forms, wake-up locks, and camera permissions. If you use your own active focus and then take a photo, remember to declare the following uses-feature tag. Other frequently used permissions here do not repeat. <uses-permission android:name= "Android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name= "Android.permission.WAKE_LOCK"/>
<uses-permission android:name= "Android.permission.CAMERA"/>


How to take photos of Android background service

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.