5 Replies Latest reply on Dec 8, 2016 7:05 AM by Darryn Campbell

    MC40 scanner blocks internal camera?

    Jacek Rys

      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