MC40 scanner blocks internal camera?

Hello,

 

I'm developing and app for MC40N0.
Build number: 01-12-03-4AJ22-K-V0-M1-072015

EMDKService version: 4.0.2.0

 

I'm using EMDKWrapper (the idea is described within this thread: EMDKWrapper class for non-Zebra devices concerns )


The app architecture is as following:

There are several separate activities which handle separate processes. In one activity we have scanning and taking a photo implemented.
Activity handles emdkWrapper class calls and Fragments embeded within it are just adding/removing listeners to proceed with scan when needed.
The fragment where the camera preview is implemented and where it's meant to take a photo does not need scanning functionality.

Now, even though it's not needed to scan we have an issue when we call onPause and then onResume methods on Photo fragment (and activity too, of course), for example by pressing the sleep button.

Then I get an error on camera initialization like this:

 

09-22 14:53:00.073 1265-1265/? E/ACRA: ACRA caught a RuntimeException for com.doddle.concession.jacek

                                       java.lang.RuntimeException: Unable to resume activity {com.jacek/com.Storage.StorageActivity}: java.lang.RuntimeException: Fail to connect to camera service

                                           at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2775)

                                           at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2804)

                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1239)

                                           at android.os.Handler.dispatchMessage(Handler.java:102)

                                           at android.os.Looper.loop(Looper.java:136)

                                           at android.app.ActivityThread.main(ActivityThread.java:5002)

                                           at java.lang.reflect.Method.invokeNative(Native Method)

                                           at java.lang.reflect.Method.invoke(Method.java:515)

                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)

                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)

                                           at dalvik.system.NativeStart.main(Native Method)

                                        Caused by: java.lang.RuntimeException: Fail to connect to camera service

                                           at android.hardware.Camera.native_setup(Native Method)

                                           at android.hardware.Camera.<init>(Camera.java:358)

                                           at android.hardware.Camera.open(Camera.java:331)

                                           at com.doddle.concession.Storage.TakePhotoFragment.initCamera(TakePhotoFragment.java:110)

                                           at com.doddle.concession.Storage.TakePhotoFragment.setupCamera(TakePhotoFragment.java:96)

                                           at com.doddle.concession.Storage.TakePhotoFragment.onResume(TakePhotoFragment.java:81)

                                           at android.support.v4.app.Fragment.performResume(Fragment.java:2020)

                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1107)

                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)

                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1234)

                                           at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:2056)

                                           at android.support.v4.app.FragmentController.dispatchResume(FragmentController.java:196)

                                           at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:505)

                                           at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:494)

                                           at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:174)

                                           at android.app.Activity.performResume(Activity.java:5348)

                                           at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2765)

                                           at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2804)

                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1239)

                                           at android.os.Handler.dispatchMessage(Handler.java:102)

                                           at android.os.Looper.loop(Looper.java:136)

                                           at android.app.ActivityThread.main(ActivityThread.java:5002)

                                           at java.lang.reflect.Method.invokeNative(Native Method)

                                           at java.lang.reflect.Method.invoke(Method.java:515)

                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)

                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)

                                           at dalvik.system.NativeStart.main(Native Method)

 

Also, I noticed some warnings in EMDK, please check it too:

 

09-22 14:57:54.840 21933-21933/? D/EMDKWrapper: setDecoders (scanner != null): true

09-22 14:57:54.880 12389-12405/? W/System.err: com.symbol.emdk.emdkservice.barcode.SvcScannerException: The scanner device is not enabled.

09-22 14:57:54.880 12389-12405/? W/System.err:     at com.symbol.emdk.emdkservice.barcode.SvcScanner.getConfig(SvcScanner.java:175)

09-22 14:57:54.880 12389-12405/? W/System.err:     at com.symbol.emdk.emdkservice.ProfileService.scnGetConfig(ProfileService.java:1072)

09-22 14:57:54.880 12389-12405/? W/System.err:     at com.symbol.emdk.emdkservice.IEMDKService$Stub.onTransact(IEMDKService.java:530)

09-22 14:57:54.900 21933-21933/? D/EMDKWrapper: Status: Failure

09-22 14:57:54.900 21933-21933/? W/System.err: com.symbol.emdk.barcode.ScannerException: Failure

09-22 14:57:54.900 21933-21933/? W/System.err:     at com.symbol.emdk.barcode.Scanner.getConfig(Scanner.java:238)

09-22 14:57:54.900 21933-21933/? W/System.err:     at com.doddle.concession.EMDK.EMDKWrapper.setDecoders(EMDKWrapper.java:322)

09-22 14:57:54.900 21933-21933/? W/System.err:     at com.doddle.concession.EMDK.EMDKWrapper.onResumeWrapped(EMDKWrapper.java:257)

09-22 14:57:54.900 21933-21933/? W/System.err:     at com.doddle.concession.EMDK.EMDKWrapper.onOpened(EMDKWrapper.java:119)

09-22 14:57:54.910 21933-21933/? W/System.err:     at com.symbol.emdk.EMDKServiceConnection.notifyonConnected(EMDKServiceConnection.java:112)

09-22 14:57:54.910 21933-21933/? W/System.err:     at com.symbol.emdk.EMDKServiceConnection.onServiceConnected(EMDKServiceConnection.java:92)

 

 

 

---------------------------------------------------------------------------

Please take a look on my EMDKWrapper class (it's attached and also pasted at the end of the description).

It's used in the following way:

 

Please take a look on my implementation on the substantial methods inside activity:

public class MyActivity extends Activity implements EMDKWrapper.IWrapperKeeper{

 

/**/

 

@Override
protected void onCreate(Bundle savedInstanceState) {

if (AppConfig.ENABLE_ZEBRA) {

 

   emdkWrapper = new EMDKWrapper(getApplicationContext());

   emdkWrapper.setCurrentProcess(RealScanCurrentProcess.STORAGE_PROCESS);

   emdkWrapper.onCreateWrapped();

  }

}

@Override
   public void onDestroy() {

   super.onDestroy();

   if (AppConfig.ENABLE_ZEBRA) {

        if (emdkWrapper != null) {

             emdkWrapper.onDestroyWrapped();

            }

       }

  }

 

 

   @Override
   public void onStop() {

   super.onStop();

   if (AppConfig.ENABLE_ZEBRA) {

        if (emdkWrapper != null) {

             emdkWrapper.onStopWrapped();

            }

       }

  }

 

 

 

   @Override
   public void onPause() {

   super.onPause();

   if (AppConfig.ENABLE_ZEBRA) {

        if (emdkWrapper != null) {

             emdkWrapper.onPauseWrapped();

            }

       }

  }

 

 

   @Override
   public void onResume() {

   super.onResume();

   if (AppConfig.ENABLE_ZEBRA) {

        if (emdkWrapper != null) {

             emdkWrapper.onResumeWrapped();

            }

       }

  }

 

@Override
public EMDKWrapper getEMDKWrapper() {

   return emdkWrapper;

}

 

 

@Override
public void addRealScanCompletedListener(RealScanLifecycleListener callback) {

   if (emdkWrapper != null) {

   emdkWrapper.addRealScanCompletedListener(callback);

  }

}

 

 

@Override
public void removeRealScanCompletedListener() {

   if (emdkWrapper != null) {

        emdkWrapper.removeRealScanCompletedListener();

  }

}

 

@Override
public void setEMDKWrapper(EMDKWrapper wrapper) {

   emdkWrapper = wrapper;

}

 

}

 

 

Please take a look on my implementation on the substantial methods inside fragment:

 

public class MyFragment extends Fragment implements RealScanLifecycleListener{

 

/**/

@Override
public void onResume() {

   super.onResume();

       initializeRealScan();

}

 

private void initializeRealScan() {

  if (AppConfig.ENABLE_ZEBRA) {

       EMDKWrapper.IWrapperKeeper wrapperKeeper = (EMDKWrapper.IWrapperKeeper) getActivity();

       wrapperKeeper.addRealScanCompletedListener(this);

  }

}

 

@Override
   public void onRealScanStarted() {

          //some UI actions take place

  }

 

@Override
public void onRealScanCompleted(String result) {

         //processing result

}

 

@Override
public void onDestroy() {

   super.onDestroy();

 

   if (AppConfig.ENABLE_ZEBRA) {

       EMDKWrapper.IWrapperKeeper wrapperKeeper = (EMDKWrapper.IWrapperKeeper) getActivity();

       wrapperKeeper.removeRealScanCompletedListener();

  }

}

 

}

 

 

This is the interface for handling scan results:

public interface RealScanLifecycleListener {

 

   void onRealScanStarted();

 

   void onRealScanCompleted(String result);

 

}

 

This is my EMDKWrapper class:

 

package com.mypackage.EMDK;

 

import android.content.Context;

import android.os.AsyncTask;

import android.util.Log;

import android.widget.Toast;

 

 

import com.symbol.emdk.EMDKManager;

import com.symbol.emdk.EMDKManager.EMDKListener;

import com.symbol.emdk.EMDKResults;

import com.symbol.emdk.barcode.BarcodeManager;

import com.symbol.emdk.barcode.ScanDataCollection;

import com.symbol.emdk.barcode.Scanner;

import com.symbol.emdk.barcode.Scanner.DataListener;

import com.symbol.emdk.barcode.Scanner.StatusListener;

import com.symbol.emdk.barcode.ScannerConfig;

import com.symbol.emdk.barcode.ScannerException;

import com.symbol.emdk.barcode.ScannerInfo;

import com.symbol.emdk.barcode.ScannerResults;

import com.symbol.emdk.barcode.StatusData;

 

import java.util.ArrayList;

 


public class EMDKWrapper implements EMDKListener, StatusListener, DataListener, BarcodeManager.ScannerConnectionListener {

 

   private static final String TAG = EMDKWrapper.class.getSimpleName() ;

   // Declare a variable to store EMDKManager object
   private EMDKManager emdkManager = null;

 

   // Declare a variable to store Barcode Manager object
   private BarcodeManager barcodeManager = null;

 

   // Declare a variable to hold scanner device to scan
   private Scanner scanner = null;

 

   private Context context;

 

   private RealScanLifecycleListener mScanningCallback;

 

   private int CURRENT_PROCESS = RealScanCurrentProcess.UNDEFINED_PROCESS;

 

   private boolean bContinuousMode = false;

 

 

  

public EMDKWrapper(Context context) {

        this.context = context;

  }

 

 

 

public void setCurrentProcess(int currentProcess) {

   this.CURRENT_PROCESS = currentProcess;

  }

 

 

   public void addRealScanCompletedListener(RealScanLifecycleListener callback) {

        if (mScanningCallback == null) {

             this.mScanningCallback = callback;

       }

  }

 

 

   public void removeRealScanCompletedListener() {

        if (mScanningCallback != null) {

             this.mScanningCallback = null;

       }

  }

 

 

   //initialization
   public boolean initializeScanner() throws ScannerException {

 

 

   if (scanner == null) {

             // Get the Barcode Manager object
             barcodeManager = (BarcodeManager) this.emdkManager.getInstance(EMDKManager.FEATURE_TYPE.BARCODE);

             // Get default scanner defined on the device
             scanner = barcodeManager.getDevice(BarcodeManager.DeviceIdentifier.DEFAULT);

             // Add data and status listeners
             scanner.addDataListener(this);

             scanner.addStatusListener(this);

             // Hard trigger. When this mode is set, the user has to manually
            // press the trigger on the device after issuing the read call.
             scanner.triggerType = Scanner.TriggerType.HARD;

             // Enable the scanner
             scanner.enable();

             // Starts an asynchronous Scan. The method will not turn ON the
            // scanner. It will, however, put the scanner in a state in which
            // the scanner can be turned ON either by pressing a hardware
            // trigger or can be turned ON automatically.
      

 

          if (scanner.isEnabled() && !scanner.isReadPending()) {

                  scanner.read();

          }

        return true;

    } else {

        return false;

   }

}

 

 

   //Listeners
   @Override
   public void onOpened(EMDKManager emdkManager) {

 

        this.emdkManager = emdkManager;

 

       onResumeWrapped();

 

  }

 

 

   @Override
   public void onClosed() {

 

        if (this.emdkManager != null) {

 

             // Remove connection listener
             removeConnectionListenerFromBarcodeManager();

 

 

             this.emdkManager.release();

             this.emdkManager = null;

       }

 

    

  }

 

 

   @Override
   public void onStatus(StatusData statusData) {

 

 

       StatusData.ScannerStates state = statusData.getState();

 

             switch (state) {

                  // Scanner is IDLE
             case IDLE:

 

 

                  if (bContinuousMode) {

                       try {

                               // An attempt to use the scanner continuously and rapidly (with a delay < 100 ms between scans)
                               // may cause the scanner to pause momentarily before resuming the scanning.
                               // Hence add some delay (>= 100ms) before submitting the next read.
                                 try {

                                     Thread.sleep(100);

                                } catch (InterruptedException e) {

                                     e.printStackTrace();

                                }

 

 

                         if (scanner.isEnabled() && !scanner.isReadPending()) {

                                 scanner.read();

                         }

                      } catch (ScannerException e) {

                           e.printStackTrace();

                      }

                 }

 

                  break;

                  // Scanner is SCANNING
             case SCANNING:

 

                  if (mScanningCallback != null) {

                       mScanningCallback.onRealScanStarted();

                    }

                  break;

                  // Scanner is waiting for trigger press
             case WAITING:

 

                  if (mScanningCallback != null) {

                       mScanningCallback.hideGreenBoarderNow();

                 }

                  break;

                  // Scanner is not enabled
             case DISABLED:

                  break;

             case ERROR:

                  break;

 

             default:

                 break;

            }

  }

 

 

   @Override
   public void onData(ScanDataCollection scanDataCollection) {

        new AsyncDataUpdated().execute(scanDataCollection);

  }

 

 

   public void onCreateWrapped() {

 

       EMDKResults results = EMDKManager.getEMDKManager(context, this);

        if (results.statusCode != EMDKResults.STATUS_CODE.SUCCESS) {

            Toast.makeText(context, context.getString(R.string.scanner_status) + context.getString(R.string.emdk_object_request_failed),                                                Toast.LENGTH_SHORT).show();

       }

  }

 

 

   public void onResumeWrapped() {

        if (emdkManager != null) {

             barcodeManager = (BarcodeManager) emdkManager.getInstance(EMDKManager.FEATURE_TYPE.BARCODE);

 

             // Add connection listener
             if (barcodeManager != null) {

                  barcodeManager.addConnectionListener(this);

            }

 

            initScanner();

            setTrigger();

            setDecoders();

            startScan();

       }

  }

 

 

   private void startScan() {

 

        if (scanner == null) {

            initScanner();

       }

 

        if (scanner != null) {

             try {

 

                    // Submit a new read.

                    if (scanner.isEnabled() && !scanner.isReadPending()) {

                            scanner.read();

                    }

 

                  bContinuousMode = true;

 

            } catch (ScannerException e) {

                 e.printStackTrace();

 

            }

       }

 

  }

 

 

   private void stopScan() {

        if (scanner != null) {

 

             try {

                  // Reset continuous flag
                  bContinuousMode = false;

                  // Cancel the pending read.
                  scanner.cancelRead();

            } catch (ScannerException e) {

                   e.printStackTrace();

            }

       }

  }

 

 

 

 

   private void setDecoders() {

         if (scanner == null) {

                 initScanner();

            }

 

         if (scanner != null) {

             try {

 

                      ScannerConfig config = scanner.getConfig();

                      config.decoderParams.i2of5.enabled = true;

                      config.decoderParams.i2of5.length1 = 1;

                      config.decoderParams.i2of5.length2 = 40;

 

                      config.decoderParams.ean8.enabled = true;

                      config.decoderParams.ean13.enabled = true;

                      config.decoderParams.code39.enabled = true;

                      config.decoderParams.code128.enabled = true;

 


                       scanner.setConfig(config);

 

                 } catch (ScannerException e) {

                     e.printStackTrace();

                 }

            }

  }

 

 

private void setTrigger() {

        if (scanner == null) {

            initScanner();

       }

 

 

        if (scanner != null) {

             scanner.triggerType = Scanner.TriggerType.HARD;

       }

  }

 

 

   private void initScanner() {

        if (scanner == null) {

 

             scanner = barcodeManager.getDevice(BarcodeManager.DeviceIdentifier.DEFAULT);

 

 

             if (scanner != null) {

 

                  scanner.addDataListener(this);

                  scanner.addStatusListener(this);

 

                  try {

                       scanner.enable();

                 } catch (ScannerException e) {

                      e.printStackTrace();

                }

            }

       }

  }

 

 

   private void removeConnectionListenerFromBarcodeManager() {

        if (barcodeManager != null) {

             barcodeManager.removeConnectionListener(this);

             barcodeManager = null;

       }

  }

 

 

   public void onDestroyWrapped() {

       deInitializeScanner();

 

       removeConnectionListenerFromBarcodeManager();

 

        if (emdkManager != null) {

             // Clean up the objects created by EMDK manager
             emdkManager.release();

             emdkManager = null;

       }

 

 

  }

 

 

   public void onStopWrapped() {

  

  }

 

 

   public void onPauseWrapped() {

 

       stopScan();

       deInitializeScanner();

 

       removeConnectionListenerFromBarcodeManager();

 

        if (emdkManager != null) {

             emdkManager.release(EMDKManager.FEATURE_TYPE.BARCODE);

       }

 

  }

 

 

   public void deInitializeScanner() {

 

        if (scanner != null) {

          

             scanner.removeDataListener(this);

             scanner.removeStatusListener(this);

 

            try {

                  scanner.cancelRead();

                  scanner.disable();

            } catch (ScannerException e) {

                 e.printStackTrace();

            }

            

             try {

                  scanner.release();

             } catch (ScannerException e) {

                 e.printStackTrace();

             }

 

 

 

             scanner = null;

       }

  }

 

 

   @Override
   public void onConnectionChange(ScannerInfo scannerInfo, BarcodeManager.ConnectionState connectionState) {

        switch (connectionState) {

             case CONNECTED:

 

                      initScanner();

                      setTrigger();

                      setDecoders();

                      startScan();

                  break;

             case DISCONNECTED:

                      deInitializeScanner();

                  break;

            }

  }

 

 

 

   public interface IWrapperKeeper {

            EMDKWrapper getEMDKWrapper();

 

             void setEMDKWrapper(EMDKWrapper wrapper);

 

             void addRealScanCompletedListener(RealScanLifecycleListener callback);

 

             void removeRealScanCompletedListener();

  }

 

 

   private class AsyncDataUpdated extends AsyncTask<ScanDataCollection, Void, String> {

 

             @Override
             protected String doInBackground(ScanDataCollection... params) {

 

                      String dataString = "";

                      ScanDataCollection datas = params[0];

                       if ((datas != null) && (datas.getResult() == ScannerResults.SUCCESS)) {

                               ArrayList<ScanDataCollection.ScanData> scanData = datas.getScanData();

                                 for (ScanDataCollection.ScanData data : scanData) {

                                          dataString = data.getData();

                                     }

                      }

 

             return dataString;

            }

 

 

             @Override

             protected void onPostExecute(String result) {

 

                       if (result.trim().isEmpty() || result.trim() == null) {

                                Toast.makeText(context, R.string.no_data_scanned, Toast.LENGTH_SHORT).show();

                      } else {

                                 switch (CURRENT_PROCESS) {

 

                                           case RealScanCurrentProcess.CHECKIN_PROCESS:

                                                    onRealScanCompleted(result);

                                                break;

                                           case RealScanCurrentProcess.STORAGE_PROCESS:

                                                    onRealScanCompleted(result);

                                                break;

                                           case RealScanCurrentProcess.COLLECTION_PROCESS:

                                                    onRealScanCompleted(result);

                                                break;

                                           case RealScanCurrentProcess.RETURNS_PROCESS:

                                                    onRealScanCompleted(result);

                                                 break;

                                           case RealScanCurrentProcess.UNDEFINED_PROCESS:

                                                    Toast.makeText(context, R.string.scan_unexpected, Toast.LENGTH_SHORT).show();

                                                break;

                                         }

                           }

                      }

 

     }

 

 

   private void onRealScanCompleted(String result) {

             if(mScanningCallback != null){

                  mScanningCallback.onRealScanCompleted(result);

            }else{

                 Log.d(TAG, "Scan callback is missing");

                 LogManager.logMessage(TAG + "Scan callback is missing");

            }

       }

 

}

 

 

The question is: should I disable EMDK for the time where I want to take a photo? Or maybe disable it one fragment before camera fragment and enable one fragment after camera fragment?


Please advice me in that matter.

 

Thanks in advance,

Jacek

Kanagal Raj Ram...
Did you call scanner.release

Did you call scanner.release before taking picture using camera?

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Jacek Rys
Yes.

Yes.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Anonymous (not verified)
Hi,The scanner warnings,

Hi,

The scanner warnings, particularly

09-22 14:57:54.880 12389-12405/? W/System.err: com.symbol.emdk.emdkservice.barcode.SvcScannerException: The scanner device is not enabled.

seems to suggest that something is out of sync between when the scanner service gets enabled or disabled from your application.

It's difficult to say exactly what the problem would be (related to fragments, related to scanner init etc).  I tried adding photo capture to the default Barcode Sample as a more simple example (branch is here:GitHub - darryncampbell/samples-emdkforandroid-5_0 at PoC-CameraWithScannerOneApp​ comparison with barcode sample is here: Comparing Zebra:BarcodeSample1...darryncampbell:PoC-CameraWithScannerOneApp · Zebra/samples-emdkforandroid-5_0 · GitHub ) The onPause() / onResume() functionality in that app works fine, being invoked when you take a picture which successfully disables the scanner hardware whilst the picture is being taken.

Sorry that's not a solution but hope that helps, for a more detailed analysis it might be necessary to contact support.

Thanks.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Jacek Rys
Hello Darryn,I tried your

Hello Darryn,

I tried your example however it's not exactly the thing that I was talking about.

In our implementation we have a fragment which has SurfaceView embeded in which we display camera.

Is is possible to contact support for more detailed analysis?

Thanks,

Jacek

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Anonymous (not verified)
Hi Jacek,Sorry the issue

Hi Jacek,

Sorry the issue still isn't solved.  I suspect using the SurfaceView is having some impact on being able to disable the Scanner or Camera as you cannot use the two simultaneously.

Support can be contacted here: Contact Tech Support

Darryn.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Log in to post comments