Working with Automated Annotations in Android

Take the following steps to start a project and add some code that demonstrates the automated annotation features of the LEADTOOLS Android Annotations.

  1. Start the Eclipse IDE.
  2. From the menu, choose File -> New -> Android Application Project....
  3. In the New Android Application dialog box, specify the project name by typing "Android Automation" in the Application Name field, and type "leadtools.androidautomation" in the Package Name field. Then keep clicking the Next button until you have finished creating the project.
  4. In the Project Explorer window, right-click on the AndroidAutomation project and select Properties... from the context menu. In the Project Properties dialog box, select the Java Build Path node, and then select the Libraries tab and click Add External JARs. Select the following .jar files:

    • leadtools.jar
    • leadtools.controls.jar
    • leadtools.annotations.engine.jar
    • leadtools.annotations.designers.jar
    • leadtools.annotations.rendering.jar
    • leadtools.annotations.automation.jar

    In the Order and Export tab, make sure all the check boxes of the added jar files are checked.

  5. In the Project Explorer window, right-click on the AndroidAutomation project and select New -> Folder... from the context menu. Then type "libs" in the Folder name and click OK.

  6. Create subfolders under libs. The subfolders created depend on the target CPU, as shown in the following table:

    CPU Folder Name
    Arm armeabi
    Arm-v7a armeabi-v7a
    X86 x86

    Note: adding multiple CPU support in one project is allowed.

  7. Copy the following lib to the target cpu folders:

    • libleadtools.so
  8. In the Project Explorer window, select res/layout/*activity_main.xml* file, and replace its content with the following:

    [XAML]

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       xmlns:tools="http://schemas.android.com/tools" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:orientation="vertical" 
       android:weightSum="1.0"  
       android:background="@android:color/black"> 
                        
       <HorizontalScrollView 
          android:layout_width="match_parent" 
          android:layout_height="wrap_content" 
          android:orientation="horizontal"> 
             <LinearLayout 
                android:layout_width="wrap_content" 
                android:layout_height="match_parent" 
                android:orientation="horizontal"> 
                   <Button 
                      android:layout_width="wrap_content" 
                      android:layout_height="wrap_content" 
                      android:text="Load Annotations" 
                      android:onClick="onLoadAnnotations"/> 
                   <Button 
                      android:layout_width="wrap_content" 
                      android:layout_height="wrap_content" 
                      android:text="Save Annotations" 
                      android:onClick="onSaveAnnotations"/> 
                   <Button 
                      android:id="@+id/btn_runmode" 
                      android:layout_width="wrap_content" 
                      android:layout_height="wrap_content" 
                      android:text="Run Mode" 
                      android:onClick="onAnnotationsModeChanged"/> 
                   <Button 
                      android:id="@+id/btn_designmode" 
                      android:layout_width="wrap_content" 
                      android:layout_height="wrap_content" 
                      android:text="Design Mode" 
                      android:onClick="onAnnotationsModeChanged"/> 
             </LinearLayout> 
       </HorizontalScrollView> 
                        
       <RelativeLayout 
          android:id="@+id/relativelayout" 
          android:layout_width="match_parent" 
          android:layout_height="0dp" 
          android:layout_weight=".96" > 
                           
          <ImageView 
             android:layout_width="match_parent" 
             android:layout_height="match_parent" 
             android:background="@android:color/white" 
             android:src="@drawable/yourfile" /> 
                              
       </RelativeLayout> 
                        
       <HorizontalScrollView  
          android:layout_width="match_parent" 
          android:layout_height="wrap_content" 
          android:orientation="horizontal"> 
          <LinearLayout 
             android:layout_width="wrap_content" 
             android:layout_height="match_parent" 
             android:orientation="horizontal"> 
             <Button 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="Select" 
                android:tag="-1" 
                android:onClick="onAnnotationsObjectChanged"/> 
             <Button 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="Pointer" 
                android:tag="-9" 
                android:onClick="onAnnotationsObjectChanged"/> 
             <Button 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="Rectangle" 
                android:tag="-3" 
                android:onClick="onAnnotationsObjectChanged"/> 
             <Button 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="Text" 
                android:tag="-12" 
                android:onClick="onAnnotationsObjectChanged"/> 
             <Button 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="Ruler" 
                android:tag="-23" 
                android:onClick="onAnnotationsObjectChanged"/> 
          </LinearLayout> 
       </HorizontalScrollView> 
    </LinearLayout> 

  9. In the previous code, you need to replace "yourfile" with the name of the file that will be drawn in the ImageViewer. To do so, perform the following steps: In the "Package Explorer", select your project, expand it. Now select "res", right-click it and select "New", and then select "Folder". In the folder name field enter "drawable" and then copy your file to that folder and replace its name into the activity_main.xml.

  10. In the Project Explorer window, edit the src/leadtools.androidautomation/*MainActivity.java* file, and add the following lines before the Main activity class:

    [Java]

    import java.io.File; 
    import java.io.FileWriter; 
    import java.util.ArrayList; 
    import leadtools.LeadMatrix; 
    import leadtools.LeadPointD; 
    import leadtools.LeadRectD; 
    import leadtools.LeadSizeD; 
    import leadtools.RasterImage; 
    import leadtools.RasterSupport; 
    import leadtools.annotations.automation.AnnAutomation; 
    import leadtools.annotations.automation.AnnAutomationManager; 
    import leadtools.annotations.engine.AnnCodecs; 
    import leadtools.annotations.engine.AnnContainer; 
    import leadtools.annotations.engine.AnnEventListener; 
    import leadtools.annotations.engine.AnnFormat; 
    import leadtools.annotations.engine.AnnObject; 
    import leadtools.annotations.engine.AnnPointerEvent; 
    import leadtools.annotations.engine.AnnPointerListener; 
    import leadtools.annotations.engine.AnnRenderingEngine; 
    import leadtools.annotations.engine.AnnUserMode; 
    import leadtools.annotations.engine.IAnnAutomationControl; 
    import leadtools.annotations.rendering.AnnAndroidRenderingEngine; 
    import android.os.Environment; 
    import android.content.Context; 
    import android.graphics.Canvas; 
    import android.view.MotionEvent; 
    import android.view.View; 
    import android.widget.RelativeLayout; 
    import android.widget.Toast; 

  11. Add the following member variables to the MainActivity class:

    [Java]

    private AnnAutomation mAutomation; 
    private final String mAnnFilePath = Environment.getExternalStorageDirectory() + "/LEAD_AnnFile.xml"; 

  12. Update the onCreate() function as shown below:

    [Java]

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
                     
    RelativeLayout layout = (RelativeLayout) findViewById(R.id.relativelayout); 
                     
    // Initialize support 
    RasterSupport.initialize(this); 
                     
    // Create automation manager object 
    AnnAutomationManager manager = new AnnAutomationManager(); 
                     
    // Create the default annotations objects 
    manager.createDefaultObjects(); 
                     
    // Initialize custom automation control 
    AutomationControl automatioControl = new AutomationControl(this); 
    layout.addView(automatioControl); 
                     
    mAutomation = new AnnAutomation(manager, automatioControl); 
    mAutomation.setActive(true); 

  13. Add the following functions:

    [Java]

    public void onLoadAnnotations(View v) 
    { 
       if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) 
       { 
          return; 
       } 
                        
       // Check if the file exist before load 
       File file = new File(mAnnFilePath); 
       if(file.exists()) 
       { 
          // Create AnnCodecs Objects 
          AnnCodecs codecs = new AnnCodecs(); 
                           
          // Load file 
          AnnContainer container = codecs.load(file, 1); 
                           
          // Clear the current annotation objects 
          mAutomation.getContainer().getChildren().clear(); 
                           
          // add the loaded objects 
          for(AnnObject annObject: container.getChildren()) 
          { 
             mAutomation.getContainer().getChildren().add(annObject); 
          } 
                           
          mAutomation.invalidate(LeadRectD.getEmpty()); 
       } 
    } 
                     
    public void onSaveAnnotations(View v) 
    { 
       if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) 
       { 
          return; 
       } 
                        
       File file = new File(mAnnFilePath); 
                        
       // if the file exist, delete it. 
       if(file.exists()) 
          file.delete(); 
                           
       try 
       { 
          // Save Annotations 
          FileWriter fw = new FileWriter(mAnnFilePath); 
          AnnCodecs codecs = new AnnCodecs(); 
          codecs.save(fw, mAutomation.getContainer(), AnnFormat.ANNOTATIONS, null, 0); 
       } 
       catch(Exception ex) 
       { 
          Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show(); 
       } 
    } 
                     
    public void onAnnotationsModeChanged(View v) 
    { 
       // Set annotation user mode 
       AnnUserMode mode = v.getId() == R.id.btn_runmode ? AnnUserMode.RUN : AnnUserMode.DESIGN; 
       mAutomation.getManager().setUserMode(mode); 
    } 
                     
    public void onAnnotationsObjectChanged(View v) 
    { 
       // set current object 
       int objectIndex = Integer.parseInt((String)v.getTag()); 
       mAutomation.getManager().setCurrentObjectId(objectIndex); 
    } 
                     
    // Custom automation control 
    private class AutomationControl extends View implements IAnnAutomationControl 
    { 
       private AnnContainer mContainer = null; 
       private AnnAndroidRenderingEngine mEngine = null; 
       private LeadPointD mOffset = new LeadPointD(0, 0); 
       private ArrayList<AnnPointerListener> mAutomationTouchListenersList = new ArrayList<AnnPointerListener>(); 
       public AutomationControl(Context context) 
       { 
          super(context); 
       } 
                        
       @Override 
       public void onDraw(Canvas canvas) 
       { 
          super.onDraw(canvas); 
          mEngine.setContext(canvas); 
          mEngine.render(LeadRectD.getEmpty()); 
          mEngine.setContext(null); 
       } 
                        
       @Override 
       public boolean onTouchEvent(MotionEvent event) 
       { 
          switch(event.getAction()) 
          { 
             case MotionEvent.ACTION_DOWN: 
                AnnPointerEvent annPointerDownEvent = new AnnPointerEvent(this, getAutomationContainer().getMapper().pointToContainerCoordinates(new LeadPointD(event.getX(), event.getY()))); 
                for(AnnPointerListener listener: mAutomationTouchListenersList) 
                listener.onPointerDown(annPointerDownEvent); 
                this.automationInvalidate(LeadRectD.getEmpty()); 
             break; 
             case MotionEvent.ACTION_MOVE: 
                AnnPointerEvent annPointerMoveEvent = new AnnPointerEvent(this, getAutomationContainer().getMapper().pointToContainerCoordinates(new LeadPointD(event.getX(), event.getY()))); 
                for(AnnPointerListener listener: mAutomationTouchListenersList) 
                listener.onPointerMove(annPointerMoveEvent); 
                this.automationInvalidate(LeadRectD.getEmpty()); 
             break; 
             case MotionEvent.ACTION_UP: 
                AnnPointerEvent annPointerUpEvent = new AnnPointerEvent(this, getAutomationContainer().getMapper().pointToContainerCoordinates(new LeadPointD(event.getX(), event.getY()))); 
                for(AnnPointerListener listener: mAutomationTouchListenersList) 
                listener.onPointerUp(annPointerUpEvent); 
                this.automationInvalidate(LeadRectD.getEmpty()); 
             break; 
          } 
                           
          return true; 
       } 
                        
       @Override 
       public void addAutomationEnabledChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void addAutomationGotFocusListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void addAutomationLostFocusListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void addAutomationSizeChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void addAutomationTouchListener(AnnPointerListener listener) 
       { 
          if(!mAutomationTouchListenersList.contains(listener)) 
             mAutomationTouchListenersList.add(listener); 
       } 
                        
       @Override 
       public void addAutomationTransformChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void addAutomationUseDpiChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void automationAttach(AnnContainer container) 
       { 
          mContainer = container; 
          mEngine = new AnnAndroidRenderingEngine(mContainer, null); 
          invalidate(); 
       } 
                        
       @Override 
       public void automationDetach() 
       { 
          mContainer = null; 
       } 
                        
       @Override 
       public void automationInvalidate(LeadRectD rc) 
       { 
          invalidate(); 
       } 
                        
       @Override 
       public AnnContainer getAutomationContainer() 
       { 
          return mContainer; 
       } 
                        
       @Override 
       public double getAutomationDpiX() 
       { 
          return 96.0; 
       } 
                        
       @Override 
       public double getAutomationDpiY() 
       { 
          return 96.0; 
       } 
                        
       @Override 
       public boolean getAutomationEnabled() 
       { 
          return true; 
       } 
                        
       @Override 
       public LeadPointD getAutomationOffset() 
       { 
          return mOffset; 
       } 
                        
       @Override 
       public LeadSizeD getAutomationSize() 
       { 
          return new LeadSizeD(getWidth(), getHeight()); 
       } 
                        
       @Override 
       public LeadMatrix getAutomationTransform() 
       { 
          return LeadMatrix.getIdentity(); 
       } 
                        
       @Override 
       public boolean getAutomationUseDpi() 
       { 
          return false; 
       } 
                        
       @Override 
       public double getAutomationXResolution() 
       { 
          return 96.0; 
       } 
                        
       @Override 
       public double getAutomationYResolution() 
       { 
          return 96.0; 
       } 
                        
       @Override 
       public RasterImage getImage() 
       { 
          return null; 
       } 
                        
       @Override 
       public AnnRenderingEngine getRenderingEngine() 
       { 
          return mEngine; 
       } 
                        
       @Override 
       public void removeAutomationEnabledChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void removeAutomationGotFocusListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void removeAutomationLostFocusListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void removeAutomationSizeChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void removeAutomationTouchListener(AnnPointerListener listener) 
       { 
          if(mAutomationTouchListenersList.contains(listener)) 
             mAutomationTouchListenersList.remove(listener); 
       } 
                        
       @Override 
       public void removeAutomationTransformChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void removeAutomationUseDpiChangedListener(AnnEventListener listener) 
       { 
       } 
                        
       @Override 
       public void setRenderingEngine(AnnRenderingEngine engine) 
       { 
          mEngine = (AnnAndroidRenderingEngine)((engine instanceof AnnAndroidRenderingEngine) ? engine : null); 
       } 
    } 

  14. Add the following line to the AndroidManifest.xml before the application tag:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  15. Build and run the program.
Help Version 20.0.2020.4.3
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2020 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS Imaging, Medical, and Document