Sunday, December 1, 2013

Android Debugging

Quick overview of some features for debugging Android app under Eclipse. I'll add them as I discover them...

If you look at the bottom right of your IDE (at least that's where it is for me), you can see the following panel. If for any reason, you prefer to edit in full screen mode (double clicking on the tab of the given source file), then this screen will pop when you run the app.


There are several tabs. If you click on Devices, you can see whatever device is connected to the computer. Also, on the same tab, you can get a snapshot of the screen of the selected device. We are going to look now into the LogCat tab. This has to do with Android logging. You can have the program output messages (logs) into your console as it is executing. Very useful to trace what is happening. Simply use something like Log.v("TAG", "Stuff to log");
  1. The "v" in log v indicates "verbose". You can use others (see the link) but I seldom do. 
  2. TAG is whatever you want to put so that you can group/filter the logs/messages. TAG can be just text that you put right there, between "" or some folks will make it part of a constants class and use Log.d(Constants.LOG, "started recording"); In our case/picture above, TAG=MyActivity.
  3. "Stuff to log" is the message itself (something that you write to yourself). You can see things like "Scoped Thread Stopped"
An older method to do this was System.out.println("started recording"); but the one above is more proper logging with all its advantages (filtering, etc...). See here the difference between the two.

Also, careful with the use of BuildConfig.DEBUG. This is intended to be able to disable the logging once you are ready for release but some folks say that it doesn't work. Although some say it does.

While all this debugging is done over USB cable, there may be a method for debugging over Wi-Fi
The link above didn't make it all that clear, so, found this other one. Unfortunately, I never got it to work (they say that you may need a rooted device). I do the adb kill-server. Then adb tcpip 5555 gives me a message as daemon started successfully but gets stuck on the "restarting in TCP mode port:5555"

Anyhow, not a great post but hope it was useful to somebody... I'll update this as I get it to work...

Android Index of Posts and Useful Links

Index of my posts and links to other useful stuff on Android, initially a bit disorganized as I keep adding things but I think it will do the work for some time :)

Installation/Environment
  1. An overview of the tools around for programming in Android the "official/standard/free" way.
  2. Install guide is very well documented by Google. Nevertheless, as I was installing OpenCV in Android I put this step by step tutorial on the installation of both. Check it if for any reason you are having problems following the official instructions.
  3. Copy a project in Eclipse
  4. Some debugging tips like logging/screen capture...
  5. 10 ADB commands (external link) and all (?) commands.
Programming
  1. Tutorial for Drawing in Android - Views/Layout Basic stuff, no dynamic...
  2. Tutorial for advanced Drawing in Android -SurfaceView and SurfaceHolder
  3. Displaying bitmaps as fast as possible (or as I possibly can :) )
  4. Importing fonts
  5. Retrieving all files in a directory
  6. Loading jpg
  7. Saving to a file in Android
  8. Flash light.
  9. Camera capture
  10. AsyncTask  
  11. Communication between threads.
  12. LruCache
  13. Creating a timer
  14. NDK: Android Native Development.
  15. Scope application (displays the audio vs time in a rolling graph in the screen)  
  16. Using some of the techniques above and OpenCV I created a 3D display, which now seems to be a similar technique to what Amazon is going to be using on their phone.
Other Code Examples
  1. For a list of examples in OpenCV, please see this index.
  2. Basic4Android example on a Baby Flashcards app.

Flash light control in Android

I am not really satisfied with this. I am just turning it on and off, but wanted to be able to adjust intensity. See some links all the way to the bottom that may be able to help on that. Got to do more research. My email to HTC was completely unfruitful... :(

Also, sorry I didn't clean it up much. It is pretty straightforward. Only other thing besides learning to turn on the LED is how we throw an alert to the user (see below for the case the phone does not have a camera flash light). But anyhow, as I got the code, here it goes (Led.java): 
 package cell0907.example.led;  
 import android.hardware.Camera;  
 import android.hardware.Camera.Parameters;  
 import android.os.Bundle;  
 import android.app.Activity;  
 import android.app.AlertDialog;  
 import android.content.DialogInterface;  
 import android.content.pm.PackageManager;  
 import android.util.Log;  
 import android.view.Menu;  
 import android.view.View;  
 import android.widget.Button;  
 import android.widget.Toast;  
 public class Led extends Activity {  
      public static Camera cam = null;// has to be static, otherwise onDestroy() destroys it  
      private Button light_switch;  
   private boolean isFlashOn;  
   private boolean hasFlash;  
   Parameters p;  
   static final String TAG="MyActivity";  
      @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.activity_led);  
           light_switch=(Button)this.findViewById(R.id.button1);  
           /*  
            * First check if device is supporting flashlight or not  
            */  
           hasFlash = getApplicationContext().getPackageManager()  
               .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);  
           if (!hasFlash) {  
             // device doesn't support flash  
             // Show alert message and close the application  
             AlertDialog alert = new AlertDialog.Builder(Led.this)  
                 .create();  
             alert.setTitle("Error");  
             alert.setMessage("Sorry, your device doesn't support flash light!");  
             alert.setButton(RESULT_OK, ALARM_SERVICE, new DialogInterface.OnClickListener() {  
               public void onClick(DialogInterface dialog, int which) {  
                 // closing the application  
                 finish();  
               }  
             });  
             alert.show();  
             return;  
           }  
           light_switch.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                     // TODO Auto-generated method stub  
               if (isFlashOn) {  
                 // turn off flash  
                    flashLightOff();  
                    light_switch.setText("Turn on");  
               } else {  
                 // turn on flash  
                    light_switch.setText("Turn off");  
                    flashLightOn();  
               }  
                }  
           });  
      }  
      public void flashLightOn() {  
           Log.v(TAG, "ON");  
        try {  
             getcamera();  
       p.setFlashMode(Parameters.FLASH_MODE_TORCH);  
       cam.setParameters(p);  
       cam.startPreview();  
       isFlashOn=true;  
        } catch (Exception e) {  
          e.printStackTrace();  
          Toast.makeText(getBaseContext(), "Exception flashLightOn()",  
              Toast.LENGTH_SHORT).show();  
        }  
      }  
      public void getcamera(){  
           if (cam==null){  
                try{  
                     Log.v(TAG, "CAMERA CONFIG");  
               cam = Camera.open();  
               p = cam.getParameters();  
                }  
                catch (RuntimeException e) {  
         Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());  
                }  
      }  
      }  
      public void flashLightOff() {  
           Log.v(TAG, "OFF");  
        if (cam!=null) try {  
            cam.stopPreview();  
            cam.release();  
            cam = null;  
               isFlashOn=false;  
        } catch (Exception e) {  
          e.printStackTrace();  
          Toast.makeText(getBaseContext(), "Exception flashLightOff",  
              Toast.LENGTH_SHORT).show();  
        }  
      }       
      @Override  
      public boolean onCreateOptionsMenu(Menu menu) {  
           // Inflate the menu; this adds items to the action bar if it is present.  
           getMenuInflater().inflate(R.menu.led, menu);  
           return false;  
      }  
      @Override  
      protected void onStart() {  
        super.onStart();  
      }  
      @Override  
      protected void onRestart() {  
        super.onRestart();  
      }  
      @Override  
      protected void onResume() {  
        super.onResume();  
      }  
      @Override  
      protected void onPause() {  
        super.onPause();  
        // on pause turn off the flash  
        flashLightOff();  
      }  
      @Override  
      protected void onStop() {  
        super.onStop();  
      }  
      @Override  
      protected void onDestroy() {  
        super.onDestroy();  
      }  
 }  


The other thing to remember is to add the following lines to the Manifest so that the app got the right permissions:
<uses-permission android:name="android.permission.CAMERA"/> 
<uses-permission android:name="android.permission.FLASHLIGHT"/>


Others:
  1. A hint on the xda-developers site. In my case I had a brightness file with 0 inside and a max_brightness file with 255 inside. I tried making the second even a zero, but my flashlight app just kept working... 
  2. This other link points to something similar and explains a way to test it quickly. Got to try.
  3. A much more elaborated flashlight example 
  4. A completely different method without using the SDK It may be worth to explore if that can do the intensity.
  5. Full source code of another flashlight app
  6. Answered question in Stackoverflow 
  7. Question without answer in Stackoverflow
  8. Please, click here to see an index of other posts on Android. 

Thursday, November 28, 2013

Importing a new font in Windows 7 and/or Android

For Android programming, see below the ***** line...
But as I was on this, I decided to check how to do it for Windows 7 :). These are the steps:
  1. Download the font file (extension ttf). There are several free sites. Check in case they are not completely free (donation, or shareware, or...). This is a site I used.
  2. For the next step, folks say to make sure that all your office programs (Outlook, Word, etc...) are closed.
  3. If the file is zip, unzip it (duh!), and then right click on the file and select Open with - Windows Font Viewer. You will see the fonts and on top, the Install button.
  4. Done! You should now be able to see them in your Font menus, in Office.
**********************************
For Android programming:
  1. Download the font file (extension ttf). There are several free sites. Check in case they are not completely free (donation, or shareware, or...). This is a site I used.
  2. If the file is zip, unzip it (duh!), and then place it in the assests directory of your project.
  3. Then use something like the following (basically extracted from this post in StackOverflow):
 protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.activity_main);       
           mdisplay = (TextView) findViewById(R.id.textView1);  
           try{  
                Typeface myTypeface = Typeface.createFromAsset(this.getAssets(),"wwDigital.ttf");  
                mdisplay.setTypeface(myTypeface);  
           }  
           catch (IllegalStateException e){  
                System.out.println("This didn't work very well");  
                return;  
           }  
           mdisplay.setTextSize(50);  
           mdisplay.setTextColor(Color.RED);  
      }  

Good luck!

PS.: Please, click here to see an index of other posts on Android. 

Sunday, November 17, 2013

Open access to publicly funded research

I always wondered why one had to pay those hefty prices for online articles... One could think that it makes sense, in general, but why, even for the ones which research had been funded by tax payers. There are lots of arguments (quality, reviews...) but honestly, I think they are mostly excuses to justify a business that in the past, with no Internet, made more sense...

Anyhow, this became a real issue for me when I was trying to research about some physical symptoms, that eventually, fortunately, proved to be nothing serious. At the time, I signed a petition to the government to solve this... And happily enough, things seem to be coming together. It seems to be fair to give this point to Obama administration although I am sure there were many folks on both sides behind this. It would be interesting to research that, but life is too short :)

I leave you with a video from Jack Andraka, a kid and a scientist, explaining what I felt few years ago...

How much waste goes into defending wrong things... Folks don't realize that eventually everything flows to the right state.

Friday, November 8, 2013

OpenCV: How to get started and index of posts

So, you want to do some cool image processing... so, here is a very basic explanation on how to get started with link/index to the stuff I posted so far.

Where to start

Basically OpenCV is a set of nice libraries that will highly expedite a lot of your work. See more detail here. You will need to call them from your program, say in C/C++ or Java.

To develop the program you will need an IDE (integrated development environment) which takes care of editing (more than a text editor, with nice support features), and allows you to "plug in", compilers, debuggers, etc... so that you can run everything from there. In my case, I am using Eclipse. Notice that you could use a different IDE. During configuration of the IDE, you tell it what compiler to use, etc... So that when you press the compile button, Eclipse calls it to generate the object file... I think you get the point...

So, install Eclipse if you don't have it. Of course, you could choose a different IDE, but sorry, no experience on that, and honestly, I have no complains about Eclipse. Great tool. In my case, I did the installation when I was planning to use it with Qt (a set of widgets for something that I was doing completely unrelated). Still, the initial portion of the installation is the same. You can see my installation experience here.

So, what do I choose, C/C++ or Java?

Not an expert on this but I believe that a lot of the initial stuff on OpenCV was done for C development. Nevertheless, I think that almost everything in OpenCV has a port to Java already. I.e., there are packages in Java equivalent to libraries in C. So, probably depends more on what language you feel comfortable with.

One thing I was thinking (and I was wrong) is that if I want to use OpenCV in Android, I better get a handle of the Java version, as that is the language to develop in that platform (see this overview on Android programming environment). Nevertheless, that it's not that truth. In Android development, there is something called the NDK which allows you to call pieces of C code (native code) from the java code (see more info here on the NDK). The funny part is that in the end, as OpenCV is pretty processing intensive, you may want to use the NDK for the OpenCV routines (native code runs much faster than java code, if you do things properly...). Bottom line, I went down the path of working with OpenCV in Java, but probably I (and you, if you prefer) could have saved part of that work, as I was more familiar with C. But as I went down that path, I end-up with Eclipse supporting both languages (that is done with the "views"). So, to install each of the languages to work with OpenCV in a PC CPU, follow:
  1. Installation to work with C/C++
  2. Installation to work with Java
To develop for an Android machine, follow this.

Note: The 3 links above are in the order of what I historically did on my case. I.e., the 3 steps may not be completely independent of each other. For instance, something got installed in step 2 that is needed for Android, but I never realized and if I had done only the third, it would not have worked. Please let me know if you got any trouble...

Coding examples

So, now that you got it installed, let's do some coding:
  1. As part of the installation of OpenCV in Java (the same link as above) we did a first tutorial where we detect faces in an image file in a PC.
  2. Creating windows in Java and drawing in them. We strip everything to get familiar with the java drawing/workings. There is no OpenCV here. I read an image file from disk and display it. No detection yet.
  3. Next, we create windows and capture webcam, i.e., not from a file, like in #1. Although we do not do any image processing, we do use OpenCV structures to be ready for the next step (processing). 
  4. One of the keys on that post is how to take a Mat structure from OpenCV and pass it to BufferedImage, for display in Java. I created a post just for that.
  5. And into image processing, we now detect the faces on the webcam stream. Notice that this is very similar (a port to Java) of the original C tutorial
  6. Then we move into detecting a ball in the image. Part of the detection is based on color. So, you got to understand the color space. See this.
  7. And then we track the ball with the PC camera/CPU.
  8. Then we start moving into Android with a first app using OpenCV.
  9. Here we track faces with OpenCV in Android, using the smart phone camera. And here I use the Android SDK for the same thing.
  10. Using the face tracking I created a 3D display, which seems to be a similar technique to what Amazon is going to be using on their phone.
  11. And finally, we port the tracking of the ball to Android, i.e., we use the smart phone camera/CPU.
  12. The last final thing that I had in plan but haven't done yet is to actually port it to Android but have the OpenCV CPU intensive routines done in a C library, with the NDK.
For the next posts I am going to be concentrating in Android development, not related to OpenCV, but I'll be back :)

Cheers!!

Tuesday, November 5, 2013

Saving to a file in Android

We create the routine apart, as part of a task, but that is irrelevant to the topic. Straight to the code...
async_save_file.java
 package com.example.saveit;  
 import java.io.DataOutputStream;  
 import java.io.File;  
 import java.io.FileOutputStream;  
 import java.text.SimpleDateFormat;  
 import java.util.Date;  
 import java.util.Locale;  
 import android.content.Context;  
 import android.os.AsyncTask;  
 import android.os.Environment;  
 import android.os.Handler;  
 import android.os.Message;  
 import android.util.Log;  
 public class async_save_file extends AsyncTask<Void, Void, Void> {  
   Context mContext;  
   private Handler threadHandler;  
   private int[] audio_buffer;  
   public async_save_file(Context context,Handler threadHandler, int[] buffer) {  
     super();  
     this.threadHandler=threadHandler;  
     this.audio_buffer=buffer;  
     mContext = context;  
       }  
   @Override  
     protected Void doInBackground(Void...params) {   
     String root = Environment.getExternalStorageDirectory().toString();  
     File myDir = new File(root + "/captured_files");    
     if (myDir.exists()) Log.v(saveit.TAG,"S: Diretory exists!");  
     else {  
          myDir.mkdirs();   
          Log.v(saveit.TAG,"S: Diretory created!");  
     }  
     String dateInString = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss",Locale.US).format(  
         new Date()).toString();  
     String fileName = dateInString + "_record.bin";  
     File file = new File (myDir, fileName);  
     Log.v(saveit.TAG,"S: file path: "+file.getPath());  
     if (file.exists ()) file.delete ();   
     try {  
          FileOutputStream out = new FileOutputStream(file);  
       DataOutputStream out_s = new DataOutputStream(out);  
           Log.v(saveit.TAG, "L: Length: "+audio_buffer.length);  
           for (int i=0;i<audio_buffer.length;i++) out_s.writeChar(audio_buffer[i]);  
           //out_s.flush();  
           //out.flush();  
           //out.close();  
           out_s.close();   
              Message.obtain(this.threadHandler, saveit.ACK_SAVED, "SAVED").sendToTarget();   
                return null;  
       } catch (Exception e) {  
            e.printStackTrace();  
                    Message.obtain(this.threadHandler, saveit.ACK_NOT_SAVED, "FAILED SAVING").sendToTarget();   
                    return null;  
       }  
   }  
 }  
Notice also the flushing of the file (most of it commented out as the last instruction takes care of the rest). See flushing the file and Will closing a dataoutputstream close also the fileoutputstream. This is called from saveit.java
 package com.example.saveit;  
 import android.os.Bundle;  
 import android.os.Handler;  
 import android.annotation.SuppressLint;  
 import android.app.Activity;  
 import android.util.Log;  
 import android.view.View;  
 import android.widget.Button;  
 import android.widget.TextView;  
 import android.widget.Toast;  
 public class saveit extends Activity {  
      public static final int ACK_SAVED=1;  
      public static final int ACK_NOT_SAVED=2;  
      public static final String TAG = "MyActivity";  
      private TextView mResult;       
      private Button save_array;                    // To trigger the whole process  
      private int[] audio_buffer={1,2,3,4};  
      @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.saveit_layout);  
           save_array=(Button)findViewById(R.id.button1);  
           mResult=(TextView)findViewById(R.id.display);  
           save_array.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                     // TODO Auto-generated method stub  
                     new async_save_file(getApplicationContext(),threadHandler,audio_buffer).execute();  
                     Log.v(TAG, "UI: SAVING");  
                     mResult.setText("SAVING");        
                }  
           });  
      }  
      ////////////////////////////////////thread Handler///////////////////////////////////////  
      @SuppressLint("HandlerLeak")  
      private Handler threadHandler = new Handler() {  
           public void handleMessage(android.os.Message msg) {  
           switch(msg.what){  
                case ACK_SAVED:  
                     Toast.makeText(getBaseContext(), (String)msg.obj, Toast.LENGTH_SHORT).show();  
                     mResult.setText("SAVED");   
                     break;  
                case ACK_NOT_SAVED:  
                     Toast.makeText(getBaseContext(), (String)msg.obj, Toast.LENGTH_SHORT).show();  
                     mResult.setText("NOT SAVED");   
                     break;  
                }            
           }  
      };  
 }  
Along the way, I also used few ways to display results/debug notices... just as example...

The manifest:
 <?xml version="1.0" encoding="utf-8"?>  
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
   package="com.example.saveit"  
   android:versionCode="1"  
   android:versionName="1.0" >  
   <uses-sdk  
     android:minSdkVersion="9"  
     android:targetSdkVersion="17" />  
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
   <application  
     android:allowBackup="true"  
     android:icon="@drawable/ic_launcher"  
     android:label="@string/app_name"  
     android:theme="@style/AppTheme" >  
     <activity  
       android:name="com.example.saveit.saveit"  
       android:label="@string/app_name" >  
       <intent-filter>  
         <action android:name="android.intent.action.MAIN" />  
         <category android:name="android.intent.category.LAUNCHER" />  
       </intent-filter>  
     </activity>  
   </application>  
 </manifest>  
And the layout:
 <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"  
   android:paddingLeft="@dimen/activity_horizontal_margin"  
   android:paddingRight="@dimen/activity_horizontal_margin"  
   android:paddingTop="@dimen/activity_vertical_margin"  
   tools:context=".MyAdderActivity" >  
   <Button  
     android:id="@+id/button1"  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content"  
     android:layout_centerHorizontal="true"  
     android:layout_marginTop="81dp"  
     android:text="@string/save_button" />  
   <TextView  
     android:id="@+id/display"  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content"  
     android:layout_below="@+id/button1"  
     android:layout_centerHorizontal="true"  
     android:text="@string/display" />  
 </RelativeLayout>  
Cheers!

PS.: Please, click here to see an index of other posts on Android.