Posts tagged activity

Android MediaPlayer

The exercise play, pause and stop a mp3 file in /res/raw folder, using android.media.MediaPlayer.

Android MediaPlayer

First of all, copy a mp3 file in /res/raw folder.

main.xml

AndroidMediaPlayer.java

package com.exercise.AndroidMediaPlayer;

import android.app.Activity;import android.media.MediaPlayer;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;

public class AndroidMediaPlayer extends Activity {

 MediaPlayer mediaPlayer; Button buttonPlayPause, buttonQuit; TextView textState;

 private int stateMediaPlayer; private final int stateMP_NotStarter = 0; private final int stateMP_Playing = 1; private final int stateMP_Pausing = 2;

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

      buttonPlayPause = (Button)findViewById(R.id.playpause);      buttonQuit = (Button)findViewById(R.id.quit);      textState = (TextView)findViewById(R.id.state);

      buttonPlayPause.setOnClickListener(buttonPlayPauseOnClickListener);      buttonQuit.setOnClickListener(buttonQuitOnClickListener);

      initMediaPlayer();

  }

  private void initMediaPlayer()  {   mediaPlayer = new  MediaPlayer();      mediaPlayer = MediaPlayer.create(AndroidMediaPlayer.this, R.raw.music);      stateMediaPlayer = stateMP_NotStarter;      textState.setText("- IDLE -");  }

  Button.OnClickListener buttonPlayPauseOnClickListener   = new Button.OnClickListener(){

   @Override   public void onClick(View v) {    // TODO Auto-generated method stub    switch(stateMediaPlayer){    case stateMP_NotStarter:     mediaPlayer.start();     buttonPlayPause.setText("Pause");     textState.setText("- PLAYING -");     stateMediaPlayer = stateMP_Playing;     break;    case stateMP_Playing:     mediaPlayer.pause();     buttonPlayPause.setText("Play");     textState.setText("- PAUSING -");     stateMediaPlayer = stateMP_Pausing;     break;    case stateMP_Pausing:     mediaPlayer.start();     buttonPlayPause.setText("Pause");     textState.setText("- PLAYING -");     stateMediaPlayer = stateMP_Playing;     break;    }

   }  };

  Button.OnClickListener buttonQuitOnClickListener = new Button.OnClickListener(){

  @Override  public void onClick(View v) {   // TODO Auto-generated method stub   mediaPlayer.stop();   mediaPlayer.release();   finish();  }   };}

Download the files.

Displays video in VideoView

The VideoView class can load images from various sources (such as resources or content providers), takes care of computing its measurement from the video so that it can be used in any layout manager, and provides various display options such as scaling and tinting.

Displays video in VideoView

main.xml

AndroidVideoView.java

package com.exercise.AndroidVideoView;

import android.app.Activity;import android.net.Uri;import android.os.Bundle;import android.widget.MediaController;import android.widget.VideoView;

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

      VideoView myVideoView = (VideoView)findViewById(R.id.videoview);

      String viewSource ="rtsp://v5.cache1.c.youtube.com/CjYLENy73wIaLQklThqIVp_AsxMYESARFEIJbXYtZ29vZ2xlSARSBWluZGV4YIvJo6nmx9DvSww=/0/0/0/video.3gp";

      myVideoView.setVideoURI(Uri.parse(viewSource));      myVideoView.setMediaController(new MediaController(this));      myVideoView.requestFocus();      myVideoView.start();

  }}

The App can run on real phone (tested on Nexus One), but cannot run on emulator with error of “Sorry, this video cannot be played”, may be limited by the actual performance of emulator.

Sorry, this video cannot be played.

To capture the URL of YouTube video in 3gp, browse to http://m.youtube.com/ and capture the URL.

Download the files.

Displays video in VideoView

The VideoView class can load images from various sources (such as resources or content providers), takes care of computing its measurement from the video so that it can be used in any layout manager, and provides various display options such as scaling and tinting.

Displays video in VideoView

main.xml

AndroidVideoView.java

package com.exercise.AndroidVideoView;

import android.app.Activity;import android.net.Uri;import android.os.Bundle;import android.widget.MediaController;import android.widget.VideoView;

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

      VideoView myVideoView = (VideoView)findViewById(R.id.videoview);

      String viewSource ="rtsp://v5.cache1.c.youtube.com/CjYLENy73wIaLQklThqIVp_AsxMYESARFEIJbXYtZ29vZ2xlSARSBWluZGV4YIvJo6nmx9DvSww=/0/0/0/video.3gp";

      myVideoView.setVideoURI(Uri.parse(viewSource));      myVideoView.setMediaController(new MediaController(this));      myVideoView.requestFocus();      myVideoView.start();

  }}

The App can run on real phone (tested on Nexus One), but cannot run on emulator with error of “Sorry, this video cannot be played”, may be limited by the actual performance of emulator.

Sorry, this video cannot be played.

To capture the URL of YouTube video in 3gp, browse to http://m.youtube.com/ and capture the URL.

Download the files.

UI testing on Android 2.1 – an simple example

This tests a simple button click action that sets the text of a TextView to “1″.
Several things were done in the following code to make it work 1) set focus on the button in the UIThread, 2) disable keyguard so that you can send the keyEvent


public class MainWindowTest extends
ActivityInstrumentationTestCase2 {
private Instrumentation mInstrumentation;
private MainWindow mActivity;
private Button mButton;
private TextView mSensorReadView;

public MainWindowTest() {
super(“com.kaipic.lightmeter”, MainWindow.class);
}

protected void setUp() throws Exception {
super.setUp();
mInstrumentation = getInstrumentation();
setActivityInitialTouchMode(false);
mActivity = getActivity();
mButton = (Button) mActivity.findViewById(R.id.read_button);
mSensorReadView = (TextView) mActivity.findViewById(R.id.sensor_read_text_view);
}

public void testClickButton() {
assertEquals(“”, mSensorReadView.getText());
mActivity.runOnUiThread(new Runnable() {
public void run() {
mButton.requestFocus();
}
});
mInstrumentation.waitForIdleSync();
this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
assertEquals(“1″, mSensorReadView.getText());
}
}


public class MainWindow extends Activity {

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
disableKeyGuardForTesting();
setContentView(R.layout.main);
Button readButton = (Button) findViewById(R.id.read_button);
readButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView sensor_read_text_view = (TextView) findViewById(R.id.sensor_read_text_view);
sensor_read_text_view.setText(“1″);
}
});
}

private void disableKeyGuardForTesting() {
KeyguardManager keyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
keyGuardManager.newKeyguardLock(“com.kaipic.lightmeter.MainWindow”).disableKeyguard();
}
}

in the AndroidManifest.xml you also need to have the following code under the tag manifest

Another exercise of SurfaceView, in a FrameLaout inside another LinearLayout

It’s another exercise of using FurfaceView in Android.

In the previous exercises “Android SurfaceView” and “Android SurfaceView, run in Thread with sleep()“, the layout was simple a FrameLayout composed of a SurfaceView only, setup using programming code setContentView(R.layout.main).

In this exercise, it’s a FrameLayout inside a LinearLayout, together with two buttons. The FrameLayout is composed of a SurfaceView. And the layout is defined in main.xml. Both the MySurfaceView(extends SurfaceView) and the MySurfaceThread(extends Thread) are implemented as separated class. When the application is running, there are two buttons over the FrameLayout with SurfaceView, a dot bounce inside the SurfaceView. User can click the first button to make the another button invisible, to change the dimension of the FrameLayout in run-time, and the SurfaceView change also accordingly.

main.xml

MySurfaceView.java

package com.exercise.AndroidMergeSurfaceView;

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{

 private MySurfaceThread thread; private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); int cx, cy, offx, offy;

 public MySurfaceView(Context context) {  super(context);  // TODO Auto-generated constructor stub  init(); }

 public MySurfaceView(Context context, AttributeSet attrs) {  super(context, attrs);  // TODO Auto-generated constructor stub  init(); }

 public MySurfaceView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle);  // TODO Auto-generated constructor stub  init(); }

  private void init(){    getHolder().addCallback(this);    thread = new MySurfaceThread(getHolder(), this);

    setFocusable(true); // make sure we get key events

    paint.setStyle(Paint.Style.STROKE);    paint.setStrokeWidth(3);    paint.setColor(Color.WHITE);

    cx = 0;    cy = 0;    offx = 10;    offy = 10;

   }

 @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {  // TODO Auto-generated method stub

 }

 @Override public void surfaceCreated(SurfaceHolder holder) {  // TODO Auto-generated method stub  thread.setRunning(true);  thread.start();

 }

 @Override public void surfaceDestroyed(SurfaceHolder holder) {  // TODO Auto-generated method stub  boolean retry = true;  thread.setRunning(false);  while (retry) {   try {    thread.join();    retry = false;   }   catch (InterruptedException e) {   }  } }

 @Override protected void onDraw(Canvas canvas) {  // TODO Auto-generated method stub  canvas.drawRGB(0, 0, 0);  canvas.drawCircle(cx, cy, 3, paint);  cx += offx;  if (cx > getWidth() || (cx < 0)){   offx *= -1;   cx += offx;  }

  cy += offy;  if (cy > getHeight() || (cy < 0)){   offy *= -1;   cy += offy;  } }}

MySurfaceThread.java

package com.exercise.AndroidMergeSurfaceView;

import android.graphics.Canvas;import android.view.SurfaceHolder;

public class MySurfaceThread extends Thread { private SurfaceHolder myThreadSurfaceHolder; private MySurfaceView myThreadSurfaceView; private boolean myThreadRun = false;

 public MySurfaceThread(SurfaceHolder surfaceHolder, MySurfaceView surfaceView) {  myThreadSurfaceHolder = surfaceHolder;  myThreadSurfaceView = surfaceView; }

 public void setRunning(boolean b) {  myThreadRun = b; }

 @Override public void run() {  // TODO Auto-generated method stub  while(myThreadRun){   Canvas c = null;

   try{    c = myThreadSurfaceHolder.lockCanvas(null);    synchronized (myThreadSurfaceHolder){     myThreadSurfaceView.onDraw(c);    }    sleep(100);   } catch (InterruptedException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }   finally{    // do this in a finally so that if an exception is thrown    // during the above, we don't leave the Surface in an    // inconsistent state    if (c != null) {     myThreadSurfaceHolder.unlockCanvasAndPost(c);    }   }  } }}

AndroidMergeSurfaceView.java

package com.exercise.AndroidMergeSurfaceView;

import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;

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

       Button buttonShowHide = (Button)findViewById(R.id.showhide);       final Button buttonDummy = (Button)findViewById(R.id.dummy);

       buttonShowHide.setOnClickListener(         new Button.OnClickListener(){

     @Override     public void onClick(View arg0) {      // TODO Auto-generated method stub      if(buttonDummy.getVisibility()==View.VISIBLE){       buttonDummy.setVisibility(View.GONE);      }      else{       buttonDummy.setVisibility(View.VISIBLE);      }     }

         }       );

   }}

Download the files.

A simple RSS reader III, show details once item clicked.

Last article “A simple RSS reader II, implement with RSSFeed & RSSItem“, only the titles shown in a List. Here, we are going to start another activity to show the details once any item in the list clicked.

A simple RSS reader III, show details once item clicked.

Most of the works from the last article “A simple RSS reader II, implement with RSSFeed & RSSItem“, with the changes lsited below.

Implement /res/layout/details.xml, it’s the layout of the activity ShowDetails.java

Implement a new Activity /src/com.exercise.AndroidRssReader/ShowDetails.java, it will be started once any item in the list clicked.

package com.exercise.AndroidRssReader;

import android.app.Activity;import android.os.Bundle;import android.widget.TextView;

public class ShowDetails extends Activity {

 @Override protected void onCreate(Bundle savedInstanceState) {  // TODO Auto-generated method stub  super.onCreate(savedInstanceState);  setContentView(R.layout.details);  TextView detailsTitle = (TextView)findViewById(R.id.detailstitle);  TextView detailsDescription = (TextView)findViewById(R.id.detailsdescription);  TextView detailsPubdate = (TextView)findViewById(R.id.detailspubdate);  TextView detailsLink = (TextView)findViewById(R.id.detailslink);

  Bundle bundle = this.getIntent().getExtras();

       detailsTitle.setText(bundle.getString("keyTitle"));       detailsDescription.setText(bundle.getString("keyDescription"));       detailsPubdate.setText(bundle.getString("keyPubdate"));       detailsLink.setText(bundle.getString("keyLink"));

 }}

Modify /src/com.exercise.AndroidRssReader/AndroidRssReader.java to start new activity once any list item clicked.

package com.exercise.AndroidRssReader;

import java.io.IOException;import java.net.MalformedURLException;import java.net.URL;import javax.xml.parsers.ParserConfigurationException;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;

import android.app.ListActivity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.TextView;

public class AndroidRssReader extends ListActivity {

 private RSSFeed myRssFeed = null;

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

       try {   URL rssUrl = new URL("http://www.gov.hk/en/about/rss/govhkrss.data.xml");   SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();   SAXParser mySAXParser = mySAXParserFactory.newSAXParser();   XMLReader myXMLReader = mySAXParser.getXMLReader();   RSSHandler myRSSHandler = new RSSHandler();   myXMLReader.setContentHandler(myRSSHandler);   InputSource myInputSource = new InputSource(rssUrl.openStream());   myXMLReader.parse(myInputSource);

   myRssFeed = myRSSHandler.getFeed();

  } catch (MalformedURLException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (ParserConfigurationException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (SAXException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }

  if (myRssFeed!=null)  {   TextView feedTitle = (TextView)findViewById(R.id.feedtitle);   TextView feedDescribtion = (TextView)findViewById(R.id.feeddescribtion);   TextView feedPubdate = (TextView)findViewById(R.id.feedpubdate);   TextView feedLink = (TextView)findViewById(R.id.feedlink);   feedTitle.setText(myRssFeed.getTitle());   feedDescribtion.setText(myRssFeed.getDescription());   feedPubdate.setText(myRssFeed.getPubdate());   feedLink.setText(myRssFeed.getLink());

   ArrayAdapter adapter =    new ArrayAdapter(this,      android.R.layout.simple_list_item_1,myRssFeed.getList());   setListAdapter(adapter);

  }   }

 @Override protected void onListItemClick(ListView l, View v, int position, long id) {  // TODO Auto-generated method stub  Intent intent = new Intent(this,ShowDetails.class);  Bundle bundle = new Bundle();  bundle.putString("keyTitle", myRssFeed.getItem(position).getTitle());  bundle.putString("keyDescription", myRssFeed.getItem(position).getDescription());  bundle.putString("keyLink", myRssFeed.getItem(position).getLink());  bundle.putString("keyPubdate", myRssFeed.getItem(position).getPubdate());  intent.putExtras(bundle);       startActivity(intent); }}

Modify AndroidManifest.xml to include the new activity.

                                                                              

Download the files.

Android Application Part 5 – The Activity and Service

After all of that, I am going to set aside any of the server programming and go straight to writing the Android portion of the system.

The System Server in Android

In this post I will add some more detail on the system server in Android. The system server is the core of the Android system and as described in the boot sequence post it is started as soon as Dalvik is initialized and running. The other system services will be running in the context of the System Server process. We will start by looking at the code that runs when the System Server starts. This code is found in the file frameworks/base/services/java/com/android/server/SystemServer.java (in the open source project tree) and we will start this discussion from the main entry point.

 /**      * This method is called from Zygote to initialize the system. This will cause the native      * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back     * up into init2() to start the Android services.     */     native public static void init1(String[] args);

    public static void main(String[] args) {        // The system server has to run all of the time, so it needs to be        // as efficient as possible with its memory usage.        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        System.loadLibrary("android_servers");        init1(args);    }

    public static final void init2() {        Log.i(TAG, "Entered the Android system server!");        Thread thr = new ServerThread();        thr.setName("android.server.ServerThread");        thr.start();    }

The first thing that happens is that the server will load a native library called android_servers that provides interfaces to native functionality. Source files for this lib are placed in frameworks/base/services/jni/. Then the native init method that will setup native services is called, init1(args), and executed. The name of the function that implements this is system_init() and the it resides in frameworks/base/cmds/system_server/library/system_init.cpp. After setting up the native services there is a callback:

runtime->callStatic("com/android/server/SystemServer", "init2");

to init2() above to create the server thread. This thread will start the remaining services in the system according to the necessary start order. A snippet of the initial sequence gives:

 // Critical services...        try {            Log.i(TAG, "Starting Power Manager.");            power = new PowerManagerService();            ServiceManager.addService(Context.POWER_SERVICE, power);

            Log.i(TAG, "Starting Activity Manager.");            context = ActivityManagerService.main(factoryTest);

            Log.i(TAG, "Starting telephony registry");            ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));

            AttributeCache.init(context);

            Log.i(TAG, "Starting Package Manager.");            pm = PackageManagerService.main(context,                    factoryTest != SystemServer.FACTORY_TEST_OFF);

            ActivityManagerService.setSystemProcess();

            mContentResolver = context.getContentResolver();

            Log.i(TAG, "Starting Content Manager.");            ContentService.main(context,                    factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);

            Log.i(TAG, "Starting System Content Providers.");            ActivityManagerService.installSystemProviders();

            Log.i(TAG, "Starting Battery Service.");            BatteryService battery = new BatteryService(context);            ServiceManager.addService("battery", battery);

            Log.i(TAG, "Starting Hardware Service.");            hardware = new HardwareService(context);            ServiceManager.addService("hardware", hardware);

            // only initialize the power service after we have started the            // hardware service, content providers and the battery service.            power.init(context, hardware, ActivityManagerService.getDefault(), battery);

            Log.i(TAG, "Starting Alarm Manager.");            AlarmManagerService alarm = new AlarmManagerService(context);            ServiceManager.addService(Context.ALARM_SERVICE, alarm);

...

We see that the power manager is started first, followed by the activity manager and the other services. There are a lot more services started after these initial and if you are interested take look in the SystemServer.java file. Each service is running in a separate Dalvik thread in the SystemServer process. To give some info on the components making up the system server we may have look at it using the DDMS tool:

We see that the main Android services such as the activity manager, package manager, alarm manager etc. are running in their separate threads but as parts of the system server process.

/Mattias

Read XML Resources in Android, using XmlResourceParser: XML parsing interface

XmlResourceParser is the XML parsing interface returned for an XML resource. This is a standard XmlPullParser interface, as well as an extended AttributeSet interface and an additional close() method on this interface for the client to indicate when it is done reading the resource.

In this exercise, we read our own XML Resource (in /res/xml folder) using XmlResourceParser, and display the contents on screen.

First of all, create a folder /res/xml, and our own XML file myxml.xml

   Hello XML Sub-Element 1    Hello XML Sub-Element 2  Sub Sub Element 

Modify main.xml

Finally, modify java code

package com.exercise.AndroidXmlResource;

import java.io.IOException;

import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;import android.content.res.Resources;import android.content.res.XmlResourceParser;import android.os.Bundle;import android.widget.TextView;

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

       TextView myXmlContent = (TextView)findViewById(R.id.my_xml);       String stringXmlContent;  try {   stringXmlContent = getEventsFromAnXML(this);   myXmlContent.setText(stringXmlContent);  } catch (XmlPullParserException e) {   // TODO Auto-generated catch block   e.printStackTrace();  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }   }

   private String getEventsFromAnXML(Activity activity)   throws XmlPullParserException, IOException   {    StringBuffer stringBuffer = new StringBuffer();    Resources res = activity.getResources();    XmlResourceParser xpp = res.getXml(R.xml.myxml);    xpp.next();    int eventType = xpp.getEventType();    while (eventType != XmlPullParser.END_DOCUMENT)    {     if(eventType == XmlPullParser.START_DOCUMENT)     {      stringBuffer.append("--- Start XML ---");     }     else if(eventType == XmlPullParser.START_TAG)     {      stringBuffer.append("nSTART_TAG: "+xpp.getName());     }     else if(eventType == XmlPullParser.END_TAG)     {      stringBuffer.append("nEND_TAG: "+xpp.getName());     }     else if(eventType == XmlPullParser.TEXT)     {      stringBuffer.append("nTEXT: "+xpp.getText());     }     eventType = xpp.next();    }    stringBuffer.append("n--- End XML ---");    return stringBuffer.toString();   }}

Download the files.

Android: how to add custom title bar

If you want to create your own custYou should do change default themes and styles for title bar. So you need to go through following steps, details are below of these section:

  1. define custom/your style derived from window title style, and that is referenced in theme
  2. derive default theme and override attributes for window title bar
  3. define custom title layout that will be shown in title bar
  4. set custom theme attribute in activity declaration that will use this custom title bar