Wednesday, July 24, 2013

Android: downloading text data from network url

reference: http://developer.android.com/training/basics/network-ops/connecting.html

1) create method to download string from url

String downloadURL(String strurl) throws IOException{
InputStream is = null;
   // Only display the first 500 characters of the retrieved
   // web page content.
   int len = 500;
   
   try{
    URL url = new URL(strurl);
    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
    conn.setReadTimeout(10000); // 10 sec
    conn.setConnectTimeout(15000); // 15 sec
    conn.setRequestMethod("GET");
    conn.setDoInput(true); // allows receiving data.
    // starts query
    conn.connect();
    int response = conn.getResponseCode();
    Log.d("connection", "response is " + response);
    is = conn.getInputStream();
   
    InputStreamReader reader = new InputStreamReader(is);
   
    char[] buff = new char[len];
    reader.read(buff);
   
    String result =  new String(buff);
    Log.d("connection", "message is " + result);
    return result;
   }
   finally{
    if(is!=null){
    is.close();
    }
   }
}

2) create class to handle download in background process
// class to handle download
// http://developer.android.com/reference/android/os/AsyncTask.html
// < Params, Progress, Result>
// Params - the type of the parameters sent to the task upon execution.
// Progress - the type of the progress units published during the background computation.
// Result - the type of the result of the background computation.
// so in this case, String is the data type of parameter sent to task, void for type of progress units, string for data type of result
class MyTask extends AsyncTask<String, Void, String>{

@Override
  // "String..." = optional parameter. can be nullable 
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
try{
return downloadURL(params[0]);
}
catch (Exception ex){
Log.d("download", "Error is " + ex.getMessage());
}
return null;
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.d("post-execute", result);
et2.setText(result); // display in EditText
}
}

3) Get connection state and execute the background process

// need to have android.permission.ACCESS_NETWORK_STATE
ConnectivityManager mgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = mgr.getActiveNetworkInfo();
if(netInfo != null && netInfo.isConnected()){
new MyTask().execute(url);
}

Monday, July 22, 2013

Android: video playback

summary:
  1. Add VideoView into the xml layout
  2. copy video into "res/raw" folder
  3. import android.widget.VideoView
  4. VideoView videoView;
  5. videoView = (VideoView)this.findViewById(R.id.videoView1);
  6. String path = "android.resource://" + this.getPackageName() + "/" + R.raw.render; // assume that the video is render.mp4
    • alternatively: can use - String path = "android.resource://" + this.getPackageName() + "/raw/render"; // assume video is render.mp4
    • can use http url to a video file online. but must add uses permission to Internet in Manifest.xml - <uses-permission android:name="android.permission.INTERNET"/>
  7. videoView.setVideoPath(path );
  8. videoView.start();

Sunday, July 21, 2013

Android: music play back

Summary:
  1. Copy the music file, eg: MP3, into the res\raw folder. if raw folder does not exist, create it. 
  2. Check R.*.java. a new id should be created. eg.: R.raw.music.
  3. import android.media.MediaPlayer;
  4. MediaPlayer player
  5. player = MediaPlayer.create(this.getApplicationContext(), R.raw.music);
  6. player.start();
  7. player.pause(); 
  8. player.seekTo(0); // seek to 0 millisec 
Alternatively, use SoundPool to manage a list of sound (eg.: sound effects for a game level): http://developer.android.com/reference/android/media/SoundPool.html
  1. import android.media.*
  2. SoundPool sndPool;
  3. sndPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); // max streams: 10; sample-rate converter quality. Currently has no effect. Use 0 for the default.
  4. int button01 = sndPool.load(this.getApplicationContext(), R.raw.button01, 1); // etc. can load more; priority of the sound. Currently has no effect. Use a value of 1 for future compatibility.
  5. (Activity) : this.setVolumeControlStream(AudioManager.STREAM_MUSIC); // to set Activity sound be controlled by hardware volume keys
  6. when it's time to play, sndPool.play(button01, 1, 1, 0, 0, 1);
    • left & right volume: 0 to 1.0
    • priority: 0 lowest
    • no loop: 0; -1 loop forever
    • play rate: 1.0

Thursday, July 18, 2013

Android: Timer thread

  1. import java.util.*;
  2. Timer timer = new Timer();
  3. create subclass of TimerTask, eg.: class MyTask extends TimerTask { ... }
  4. add "public void run()" method in subclass
  5. timer.schedule(new MyTask(), 0, 30); // assume no delay and 30 millisec interval 
  6. timer.cancel(); // for cleanup. to start timer again, need to instantiate:  new Timer(); then schedule(...)
  7. if using "protected void onPause()" or onResume(), ensure that super.onPause(), etc is called. 
  8. if need to refresh View UI, then use postInvalidate() instead of invalidate(). else will have exception
Activity life cycle (to understand when to stop Timer to prevent waste of resources):


Android: View + touch listener

  1. implements View.OnTouchListener
  2. add public boolean onTouch(View v, MotionEvent event) method
  3. view.setOnTouchListener(this);
  4. event.getX() or getY() to get position of touch
sample code:
public class SecondActivity extends Activity implements View.OnTouchListener{
MyCanvas c;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
c = (MyCanvas)this.findViewById(R.id.myCanvas1);
tv = (TextView)this.findViewById(R.id.textView1);
c.setOnTouchListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.second, menu);
return true;
}
public boolean onTouch(View v, MotionEvent event){
if(v ==c ){
tv.setText("touched: " + event.getX() + ", " + event.getY());
}
return false;
}
}

Wednesday, July 17, 2013

Android: custom View with draw + xml layout

create custom View class:
public class MyCanvas extends View {
int x = 0;
public MyCanvas(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

Paint paint = new Paint();
Rect rect = new Rect();
protected void onDraw(Canvas canvas){
paint.setColor(0xFF999999);
rect.set(x, 100, 200, 150);
canvas.drawRect(rect, paint);
}
public void move(){
x+=5;
this.invalidate(); // redraw
}
}

xml 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=".MainActivity" android:id="@+id/layout1">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="21dp"
        android:text="Button" />

    <com.boon.MyCanvas
        android:id="@+id/myCanvas1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/button1"
        android:background="#CCCCCC" />

</RelativeLayout>

MainActivity.java: 
public class MainActivity extends Activity implements View.OnClickListener{
Button b;
MyCanvas c;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button)this.findViewById(R.id.button1);
b.setOnClickListener(this);
c = (MyCanvas) this.findViewById(R.id.myCanvas1);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
c.move();
}

}

Wednesday, July 10, 2013

Android: Accelerometer + Gyroscope

summary:
  1. import android.hardware.*;
  2. SensorManager mSensorManager;
  3. Sensor accSensor, gyroSensor;
  4. mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  5. accSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  6. gyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
  7. implements SensorEventListener 
  8. public void onSensorChanged(SensorEvent event) { ... }
  9. mSensorManager.registerListener(this, accSensor, SensorManager.SENSOR_DELAY_UI);
  10. mSensorManager.registerListener(this, gyroSensor, SensorManager.SENSOR_DELAY_UI);
  11. get the x, y, z values using event.values[0], [1], [2] in the onSensorChanged method
  12. mSensorManager.unregisterListener(this, accSensor);
  13. mSensorManager.unregisterListener(this, gyroSensor);