Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

31 August, 2013

Android Rtsp Usage



Loved my Samsung Galaxy but recently replaced it.  Result is that I have a relatively decent smart phone with little, to no, purpose in life.  Repurposing as a RTSP server device seemed like a reasonable task.

Reviewed a series of video server apps in the Google Play Store, but only one that worked well for me with Linux RTSP clients was:
https://play.google.com/store/apps/details?id=com.pas.webcam

After installing the app and short configuration, you start the server by clicking the 'Start server' button in the video preference activity.

Once the phone streaming is running, it displays a live view of the scene and the connection URL.

Open it with VLC and you're cookin' with bacon:


$ cvlc http://192.168.0.157:8080/video






VoilĂ .

08 September, 2012

Stress Testing Android Application Activity Start/Stop

One of the things I find before delivering Android applications is the impact of starting and stopping the application in a rapid manner. It's common that key stroke and touch handlers get invoked before all the necessary resources have been created, or after they have been released. Starting an application, followed by hitting the back button or home button can often result in calls to your application handlers or scheduled behavior after onStop() has been invoked. I find the following script assists in stress testing this form of behavior:

#!/bin/bash


for t in {0..5}; do
  for i in {0..10}; do
    adb -s emulator-5554 shell am start -a android.intent.action.MYAPPNAME -n com.abc.myappname/com.abc.myappname.MyAppName
    sleep $t
    adb shell input keyevent 3
    sleep 5
  done
done

The above script will repeatedly start the application, wait X seconds, then post the 'home' keyevent. If my app passes this test, and a series of monkey tests I'm pretty confident the users won't experience unexpected crashes. Cheers.

06 September, 2012

Customizing Views with Android

My wife, a software engineer as well, pointed out today that I've been making customizing views more difficult than they have to be.  While I've been customizing views, buttons, and the like for some time I've felt that I needed to dynamically create the objects because I didn't think you could specify them in the XML layout.  Fortunately, I was incorrect.

Consider extending the ImageView class, demonstrated in the following example;


package com.abc.customview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.content.Context;
import android.util.AttributeSet;

class MyCanvasView extends ImageView {
        public MyCanvasView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
        }

        public MyCanvasView(Context context, AttributeSet attrs) {
                super(context, attrs);
        }

        public MyCanvasView(Context context) {
                super(context);
        }
};

public class CustomView extends Activity
{

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}
Normal XML layout would take the form;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Hello World, CustomView"
    />
  <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="#00000000"
    android:layout_gravity="center"
    android:src="@drawable/background"
    android:layout_weight="85"/>
</LinearLayout>
Using the extended class requires replacing the "ImageView" class specifier to our extended sub-class using full package namespace;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Hello World, CustomView"
    />
  <com.abc.customview.MyCanvasView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="#00000000"
    android:layout_gravity="center"
    android:src="@drawable/background"
    android:layout_weight="85"/>
</LinearLayout>
Cheers.

28 July, 2012

Android Version Distributions

Came across this site, gives statistics of Android versions currently used:


30 April, 2012

Android Library Reuse

Well, it took me some time, but I finally uncover my original findings concerning creating an Android reuse library. Examples seem tough to come-by, so I'll post what I discovered. The overall objective is to define a reuse package that contains common source and resources. For the sake of this discussion, our reuse package will be defined as com.abc.lib, our sample project utilizing the library packaged as com.abc.sample01; First, let's create our reuse library project:

$ android create lib-project --name Lib --target 4 --path Lib --package com.abc.lib

Next, populate the source with library package contents:

$ mkdir -p Lib/src/com/abc/lib
$ cat LogUtils.java 
package com.abc.lib;

public class LogUtils {
  static public void Log (String msg) {
  }
}
$ cp ./LogUtils.java Lib/src/com/abc/lib

Building the library results in a JAR file located in bin.

/var/tmp/temp/Lib$ ant debug
Buildfile: /var/tmp/temp/Lib/build.xml

-set-mode-check:

-set-debug-files:

-set-debug-mode:

-debug-obfuscation-check:

-setup:
     [echo] Gathering info for Lib...
    [setup] Android SDK Tools Revision 16
    [setup] Project Target: Android 3.0
    [setup] API level: 11
    [setup] Project Type: Android Library
    [setup] 
    [setup] ------------------
    [setup] Resolving library dependencies:
    [setup] No library dependencies.
    [setup] 
    [setup] ------------------
    [setup] 
    [setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.

-build-setup:
     [echo] Creating output directories if needed...
    [mkdir] Created dir: /var/tmp/temp/Lib/bin
    [mkdir] Created dir: /var/tmp/temp/Lib/bin/res
    [mkdir] Created dir: /var/tmp/temp/Lib/gen
    [mkdir] Created dir: /var/tmp/temp/Lib/bin/classes

-pre-build:

-code-gen:
     [echo] ----------
     [echo] Handling aidl files...
     [aidl] No AIDL files to compile.
     [echo] ----------
     [echo] Handling RenderScript files...
[renderscript] No RenderScript files to compile.
     [echo] ----------
     [echo] Handling Resources...
     [aapt] Generating resource IDs...

-pre-compile:

-compile:
    [javac] Compiling 2 source files to /var/tmp/temp/Lib/bin/classes
     [echo] Creating library output jar file...
      [jar] Building jar: /var/tmp/temp/Lib/bin/classes.jar

-post-compile:

-obfuscate:

-dex:
     [echo] Library project: do not convert bytecode...

-crunch:
   [crunch] Crunching PNG Files in source dir: /var/tmp/temp/Lib/res
   [crunch] To destination dir: /var/tmp/temp/Lib/bin/res
   [crunch] Crunched 0 PNG files to u
   [crunch] pdate cache

-package-resources:
     [echo] Library project: do not package resources...

-package:
     [echo] Library project: do not package apk...

-do-debug:
     [echo] Library project: do not create apk...

debug:
[propertyfile] Creating new property file: /var/tmp/temp/Lib/bin/build.prop
[propertyfile] Updating property file: /var/tmp/temp/Lib/bin/build.prop
[propertyfile] Updating property file: /var/tmp/temp/Lib/bin/build.prop
[propertyfile] Updating property file: /var/tmp/temp/Lib/bin/build.prop

BUILD SUCCESSFUL
Total time: 2 seconds
/var/tmp/temp/Lib$ 

The contents of the JAR file can confirm the existence of the LogUtils class.
/var/tmp/temp/Lib$ jar -tf ./bin/classes.jar 
META-INF/
META-INF/MANIFEST.MF
com/
com/abc/
com/abc/lib/
com/abc/lib/LogUtils.class
Next, let's create a project that will utilize the common reuse library.

$ android create project --package com.abc.sample01 --activity Sample01 --target 2 --path Sample01
We add the library dependency by specifying the relative path to the library.
$ android update project --target 4 --path Sample01 --library ../Lib
Finally, update the project to ensure it all takes affect.
$ android update project --path Sample01
Our sample activity can reference our common library components as follows;

/var/tmp/temp/Sample01$ cat src/com/abc/sample01/Sample01.java 
package com.abc.sample01;

import android.app.Activity;
import android.os.Bundle;
import com.abc.lib.LogUtils;

public class Sample01 extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        LogUtils.Log("hello");
    }
}

Building the sample project via 'ant debug' somewhat duplicates the resources and source in the referencing project.

Kinda rough post, but it hits most of the generals.

10 October, 2010

Hola Android -- Stage 4

Let's expand on our user interface example by incorporating an 'icon menu' on the main activity. This menu will be activated upon pressing the 'menu button'.

Unlike the incorporation of previous menus, this addition will take place exclusively in the main activity.

We start by defining the menu items in a resource layout XML file as follows:

user@River:~/HolaAndroid$ cat -n res/layout/iconmenu.xml
1    <?xml version="1.0" encoding="utf-8"?>
2    <menu xmlns:android="http://schemas.android.com/apk/res/android">
3        <item android:id="@+id/config"
4              android:title="Config" />
5        <item android:id="@+id/quit"
6              android:title="Quit" />
7    </menu>
8
user@River:~/HolaAndroid$


Next, we modify our HolaAndroid.java source to include the rendering of the menu upon pressing the menu button. We're making use of the Toast utilities to demonstrate the button press. Specifically, lines 13-14 and 57-99 were introduced to get our desired behavior.


user@River:~/HolaAndroid$ cat -n src/com/example/holaandroid/HolaAndroid.java
    1 package com.example.holaandroid;
    2 
    3 import android.app.Activity;
    4 import android.os.Bundle;
    5 import android.widget.Button;
    6 import android.view.View;
    7 import android.view.View.OnClickListener;
    8 import android.util.Log;
    9 import android.content.Intent;
   10 import android.view.Menu;
   11 import android.view.MenuItem;
   12 import android.view.MenuInflater;
   13 import android.widget.Toast;
   14 import android.view.Gravity;
   15 
   16 
   17 public class HolaAndroid extends Activity
   18 {
   19     private static final String ClassName = "HolaAndroid";
   20     private Button b1_;
   21     private Button b2_;
   22 
   23     /** Called when the activity is first created. */
   24     @Override
   25     public void onCreate(Bundle savedInstanceState)
   26     {
   27         final String MethodName = "onStart";
   28 
   29         super.onCreate(savedInstanceState);
   30         setContentView(R.layout.main);
   31 
   32         b1_ = (Button)this.findViewById(R.id.button1);
   33         b1_.setOnClickListener(new OnClickListener() {
   34                 public void onClick (View v){
   35                   Log.d(ClassName+"::"+MethodName, "entry");
   36                   finish();
   37                 }
   38             });
   39         b2_ = (Button)this.findViewById(R.id.button2);
   40         b2_.setOnClickListener(new OnClickListener() {
   41                 public void onClick (View v){
   42                   Log.d(ClassName+"::"+MethodName, "entry");
   43                   createMenu2();
   44                   Log.d(ClassName+"::"+MethodName, "entry");
   45                 }
   46             });
   47     }
   48     private static final int ACTIVITY_CREATE=0;
   49     private void createMenu2() {
   50       final String MethodName = "createMenu2";
   51       Log.d(ClassName+"::"+MethodName, "entry");
   52       Intent i = new Intent(this, Menu2.class);
   53       startActivityForResult(i, ACTIVITY_CREATE);
   54       Log.d(ClassName+"::"+MethodName, "exit");
   55     }
   56 
   57     @Override
   58     public boolean onCreateOptionsMenu(Menu menu)
   59     {
   60         final String MethodName = "onCreateOptionsMenu";
   61         Log.d(ClassName+"::"+MethodName, "entry");
   62         MenuInflater inflater = getMenuInflater();
   63         inflater.inflate(R.layout.iconmenu, menu);
   64         Log.d(ClassName+"::"+MethodName, "exit");
   65         return true;
   66     }
   67 
   68     @Override
   69     public boolean onOptionsItemSelected(MenuItem item)
   70     {
   71         final String MethodName = "onOptionsItemSelected";
   72         Log.d(ClassName+"::"+MethodName, "entry");
   73         boolean retVal=false;
   74         switch (item.getItemId()) {
   75           case R.id.config:
   76               retVal=true;
   77               showMsg("Config Select");
   78             break;
   79           case R.id.quit:
   80               retVal=true;
   81               showMsg("Quit Select");
   82               finish();
   83             break;
   84         default:
   85           retVal=super.onOptionsItemSelected(item);
   86         }
   87         Log.d(ClassName+"::"+MethodName, "exit");
   88         return retVal;
   89     }
   90 
   91     private void showMsg(String msg) {
   92       final String MethodName = "showMsg";
   93       Log.d(ClassName+"::"+MethodName, "entry");
   94       Toast toast = Toast.makeText(this, msg, Toast.LENGTH_LONG);
   95       toast.setGravity(Gravity.CENTER, toast.getXOffset() / 2, toast.getYOffset() / 2);
   96       toast.show();
   97       Log.d(ClassName+"::"+MethodName, "exit");
   98     }
   99 
  100 }
user@River:~/HolaAndroid$


Make it, and run it and you'll get the following result.