This session in Google I/O 2014, Cardboard: VR for Android, discuss how to build immersive 3D experiences for Android. Give a deep dive into 3D side-by-side rendering, head tracking, and user interaction principles. Introduce a new open source VR toolkit and walk through using it to create a sample immersive app.
Monday, June 30, 2014
Cardboard: Virtual Reality (VR) for Android
Cardboard is a simple DIY enclosure that transforms a phone into a basic virtual reality headset and the accompanying open software toolkit. Cardboard makes it easy for both users and developers to experiment with VR.
This session in Google I/O 2014, Cardboard: VR for Android, discuss how to build immersive 3D experiences for Android. Give a deep dive into 3D side-by-side rendering, head tracking, and user interaction principles. Introduce a new open source VR toolkit and walk through using it to create a sample immersive app.
This session in Google I/O 2014, Cardboard: VR for Android, discuss how to build immersive 3D experiences for Android. Give a deep dive into 3D side-by-side rendering, head tracking, and user interaction principles. Introduce a new open source VR toolkit and walk through using it to create a sample immersive app.
Sunday, June 29, 2014
The ART runtime
ART is an evolution of the Android runtime, and was first made available as an option on Android 4.4, KitKat. It comes with improvements in the garbage collector, threading and locking model, compiler and runtime performance. This session in Google I/O 2014, The ART runtime, focus on all of the improvements have been made to the Android runtime.
Thursday, June 26, 2014
The L Developer Preview is available for download now
The Android L Developer Preview is available for download. It lets developers explore features and capabilities of the upcoming Android L release and get started developing and testing on the new platform. You can take a look at the developer features and APIs in the API Overview page.
What's new in Android and Android Development Tools@Google I/O 2014
Join for a thrilling, guided tour of all the latest developments in Android technologies and APIs. Cover everything that's new and improved in the Android platform.
Provide an in depth tour of the Android development tools and take a closer look at everything new - along with tips and tricks for getting the most out of them!
Provide an in depth tour of the Android development tools and take a closer look at everything new - along with tips and tricks for getting the most out of them!
Wednesday, June 25, 2014
Cardboard, Virtual reality on your smartphone
Cardboard is a no-frills enclosure that transforms a phone into a basic VR headset, and the accompanying open software toolkit that makes writing VR software as simple as building a web or mobile app.
Install Cardboard app puts virtual reality on your smartphone. Try a variety of immersive demos on Android, and get inspired to build your own using the VR Toolkit at http://g.co/cardboard.
• Earth: Fly where your fancy takes you on Google Earth.
• Tour Guide: Visit Versailles with a local guide.
• YouTube: Watch popular YouTube videos on a massive screen.
• Exhibit: Examine cultural artifacts from every angle.
• Photo Sphere: Look around the photo spheres you've captured.
• Street Vue: Drive through Paris on a summer day.
• Windy Day: Follow the story (and the hat) in this interactive animated short from Spotlight Stories.
To fully enjoy this app you'll need a Cardboard viewer. You can make your own using the instructions at http://g.co/cardboard to build your viewer.
more: Cardboard: Virtual Reality (VR) for Android
Install Cardboard app puts virtual reality on your smartphone. Try a variety of immersive demos on Android, and get inspired to build your own using the VR Toolkit at http://g.co/cardboard.
• Earth: Fly where your fancy takes you on Google Earth.
• Tour Guide: Visit Versailles with a local guide.
• YouTube: Watch popular YouTube videos on a massive screen.
• Exhibit: Examine cultural artifacts from every angle.
• Photo Sphere: Look around the photo spheres you've captured.
• Street Vue: Drive through Paris on a summer day.
• Windy Day: Follow the story (and the hat) in this interactive animated short from Spotlight Stories.
To fully enjoy this app you'll need a Cardboard viewer. You can make your own using the instructions at http://g.co/cardboard to build your viewer.
more: Cardboard: Virtual Reality (VR) for Android
Detect AnimationDrawable.isRunning() to toggle start/stop animation
This example base on the old example "Start and Stop frame animation with AnimationDrawable". When button clicked, it read AnimationDrawable.isRunning() and call AnimationDrawable.start() or AnimationDrawable.stop() to toggle the animation.
Download the png files and copy /res/anim/anim_android.xml here.
/res/layout/main.xml
AndroidAnimationActivity.java
Download the files.
Next:
- Determine end of animation to start another animation
Download the png files and copy /res/anim/anim_android.xml here.
/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<Button
android:id="@+id/startstopanimation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start/Stop Animation" />
<ImageView
android:id="@+id/myanimation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@anim/anim_android"
/>
</LinearLayout>
AndroidAnimationActivity.java
package com.exercise.AndroidAnimation;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class AndroidAnimationActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView myAnimation = (ImageView)findViewById(R.id.myanimation);
final AnimationDrawable myAnimationDrawable
= (AnimationDrawable)myAnimation.getDrawable();
Button startStopAnimation = (Button)findViewById(R.id.startstopanimation);
startStopAnimation.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
if(myAnimationDrawable.isRunning()){
myAnimationDrawable.stop();
}else{
myAnimationDrawable.start();
}
}});
}
}
Download the files.
Next:
- Determine end of animation to start another animation
Tuesday, June 24, 2014
Thursday, June 19, 2014
An Introduction to Android Wear
Google release new video to give an overview of the current Android Wear developer preview.
Wednesday, June 18, 2014
Implement arrow-like PathDashPathEffect
Last example "Implement running dash path, using PathDashPathEffect" with path of circle. It's modified to create custom path to show running arrow-like PathDashPathEffect.
Modify MyView.java in last example.
Other files have no changed, re-list here:
MyShape.java
MainActivity.java
activity_main.xml
Download the files.
More example of Drawing Path on canvas of custom View.
Modify MyView.java in last example.
package com.example.androiddrawpath;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
public class MyView extends View {
MyShape myShape;
float ratioRadius, ratioInnerRadius;
int numberOfPoint = 3; //default
float rotate;
//corresponding to UI element
TextView textLayerInfo;
Path dashPath;
float phase;
float advance;
public MyView(Context context) {
super(context);
initMyView();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
public void initMyView(){
myShape = new MyShape();
dashPath = new Path();
dashPath.moveTo(5, -5);
dashPath.lineTo(45, -5);
dashPath.lineTo(40, 0);
dashPath.lineTo(45, 5);
dashPath.lineTo(5, 5);
dashPath.lineTo(0, 0);
dashPath.close();
phase = 0.0f;
advance = 60.0f;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
long starting = System.nanoTime();
int w = getWidth();
int h = getHeight();
if((w==0) || (h==0)){
return;
}
float x = (float)w/2.0f;
float y = (float)h/2.0f;
float radius, innerRadius;
if(w > h){
radius = h * ratioRadius;
innerRadius = h * ratioInnerRadius;
}else{
radius = w * ratioRadius;
innerRadius = w * ratioInnerRadius;
}
myShape.setStar(x, y, radius, innerRadius, numberOfPoint);
//Save and rotate canvas
canvas.save();
canvas.rotate(rotate, x, y);
phase++;
PathDashPathEffect pathDashPathEffect =
new PathDashPathEffect(dashPath, advance, phase, PathDashPathEffect.Style.MORPH);
Paint paintDash = myShape.getPaint();
paintDash.setPathEffect(pathDashPathEffect);
canvas.drawPath(myShape.getPath(), myShape.getPaint());
//restore canvas
canvas.restore();
long end = System.nanoTime();
String info = "myView.isHardwareAccelerated() = " + isHardwareAccelerated() + "\n"
+ "canvas.isHardwareAccelerated() = " + canvas.isHardwareAccelerated() + "\n"
+ "processing time (reference only) : " + String.valueOf(end - starting) + " (ns)";
textLayerInfo.setText(info);
invalidate();
}
public void setShapeRadiusRatio(float ratio){
ratioRadius = ratio;
}
public void setShapeInnerRadiusRatio(float ratio){
ratioInnerRadius = ratio;
}
public void setNumberOfPoint(int pt){
numberOfPoint = pt;
}
public void passElements(TextView textLayerInfo){
this.textLayerInfo = textLayerInfo;
}
public void setShapeRotate(int rot){
rotate = (float)rot;
}
}
Other files have no changed, re-list here:
MyShape.java
package com.example.androiddrawpath;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
public class MyShape {
private Paint paint;
private Path path;
public MyShape() {
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
//paint.setStyle(Paint.Style.FILL);
//paint.setStyle(Paint.Style.FILL_AND_STROKE);
path = new Path();
}
public void setCircle(float x, float y, float radius, Path.Direction dir){
path.reset();
path.addCircle(x, y, radius, dir);
}
public void setStar(float x, float y, float radius, float innerRadius, int numOfPt){
double section = 2.0 * Math.PI/numOfPt;
path.reset();
path.moveTo(
(float)(x + radius * Math.cos(0)),
(float)(y + radius * Math.sin(0)));
path.lineTo(
(float)(x + innerRadius * Math.cos(0 + section/2.0)),
(float)(y + innerRadius * Math.sin(0 + section/2.0)));
for(int i=1; i<numOfPt; i++){
path.lineTo(
(float)(x + radius * Math.cos(section * i)),
(float)(y + radius * Math.sin(section * i)));
path.lineTo(
(float)(x + innerRadius * Math.cos(section * i + section/2.0)),
(float)(y + innerRadius * Math.sin(section * i + section/2.0)));
}
path.close();
}
public Path getPath(){
return path;
}
public Paint getPaint(){
return paint;
}
}
MainActivity.java
package com.example.androiddrawpath;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MainActivity extends Activity {
SeekBar rotateBar;
TextView rotateText;
SeekBar radiusBar, innerRadiusBar;
MyView myView;
SeekBar ptBar;
TextView textPt;
final static int MIN_PT = 3;
RadioButton optLayerTypeNone, optLayerTypeSoftware, optLayerTypeHardware;
TextView textLayerInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
radiusBar = (SeekBar) findViewById(R.id.radiusbar);
innerRadiusBar = (SeekBar)findViewById(R.id.innerradiusbar);
myView = (MyView) findViewById(R.id.myview);
float defaultRatio = (float) (radiusBar.getProgress())
/ (float) (radiusBar.getMax());
myView.setShapeRadiusRatio(defaultRatio);
float defaultInnerRatio = (float) (innerRadiusBar.getProgress())
/ (float) (innerRadiusBar.getMax());
myView.setShapeInnerRadiusRatio(defaultInnerRatio);
radiusBar.setOnSeekBarChangeListener(radiusBarOnSeekBarChangeListener);
innerRadiusBar.setOnSeekBarChangeListener(innerRadiusBarOnSeekBarChangeListener);
textPt = (TextView)findViewById(R.id.pttext);
ptBar = (SeekBar)findViewById(R.id.ptbar);
ptBar.setOnSeekBarChangeListener(ptBarOnSeekBarChangeListener);
optLayerTypeNone = (RadioButton)findViewById(R.id.typeNone);
optLayerTypeSoftware = (RadioButton)findViewById(R.id.typeSoftware);
optLayerTypeHardware = (RadioButton)findViewById(R.id.typeHardware);
textLayerInfo = (TextView)findViewById(R.id.typeinfo);
myView.passElements(textLayerInfo);
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
optLayerTypeNone.setOnCheckedChangeListener(optLayerTypeOnCheckedChangeListener);
optLayerTypeSoftware.setOnCheckedChangeListener(optLayerTypeOnCheckedChangeListener);
optLayerTypeHardware.setOnCheckedChangeListener(optLayerTypeOnCheckedChangeListener);
rotateText = (TextView)findViewById(R.id.rottext);
rotateBar = (SeekBar)findViewById(R.id.rotatebar);
rotateBar.setOnSeekBarChangeListener(rotateBarOnSeekBarChangeListener);
myView.setRotation(0); //set default rotate degree
};
OnCheckedChangeListener optLayerTypeOnCheckedChangeListener =
new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(optLayerTypeNone.isChecked()){
myView.setLayerType(View.LAYER_TYPE_NONE, null);
}else if(optLayerTypeSoftware.isChecked()){
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}else{
myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
myView.invalidate();
}};
OnSeekBarChangeListener radiusBarOnSeekBarChangeListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
float ratio = (float) (radiusBar.getProgress())
/ (float) (radiusBar.getMax());
myView.setShapeRadiusRatio(ratio);
myView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
OnSeekBarChangeListener innerRadiusBarOnSeekBarChangeListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
float ratio = (float) (innerRadiusBar.getProgress())
/ (float) (innerRadiusBar.getMax());
myView.setShapeInnerRadiusRatio(ratio);
myView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
OnSeekBarChangeListener ptBarOnSeekBarChangeListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
int pt = progress + MIN_PT;
textPt.setText("number of point in polygon: " + String.valueOf(pt));
myView.setNumberOfPoint(pt);
myView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
OnSeekBarChangeListener rotateBarOnSeekBarChangeListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
int degree = progress-180;
rotateText.setText("rotate : " + degree + " degree");
myView.setShapeRotate(degree);
myView.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
}
activity_main.xml
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androiddrawpath.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="radius(%)"/>
<SeekBar
android:id="@+id/radiusbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="inner radius(%)"/>
<SeekBar
android:id="@+id/innerradiusbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="25" />
<TextView
android:id="@+id/pttext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="number of point in polygon: 3"/>
<SeekBar
android:id="@+id/ptbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="0" />
<TextView
android:id="@+id/rottext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="rotate :"/>
<SeekBar
android:id="@+id/rotatebar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="360"
android:progress="180" />
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton android:id="@+id/typeNone"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="LAYER_TYPE_NONE"/>
<RadioButton android:id="@+id/typeSoftware"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="LAYER_TYPE_SOFTWARE"/>
<RadioButton android:id="@+id/typeHardware"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="LAYER_TYPE_HARDWARE"/>
</RadioGroup>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/typeinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<com.example.androiddrawpath.MyView
android:id="@+id/myview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</LinearLayout>
Download the files.
More example of Drawing Path on canvas of custom View.
Tuesday, June 17, 2014
Monday, June 16, 2014
Implement running dash path, using PathDashPathEffect
Example to implement running dash path, using PathDashPathEffect.
MyView.java
Other files, refer to last example.
Download the files.
More example of Drawing Path on canvas of custom View.
Modify from previous example "DashPathEffect, apply dash effect on path", implement PathDashPathEffect. In order to make it running, advance phase of PathDashPathEffect, and call invalidate() in onDraw() method.
MyView.java
package com.example.androiddrawpath;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.Path.Direction;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
public class MyView extends View {
MyShape myShape;
float ratioRadius, ratioInnerRadius;
int numberOfPoint = 3; //default
float rotate;
//corresponding to UI element
TextView textLayerInfo;
Path dashPath;
float phase;
public MyView(Context context) {
super(context);
initMyView();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
public void initMyView(){
myShape = new MyShape();
dashPath = new Path();
dashPath.addCircle(0, 0, 3, Direction.CCW);
phase = 0.0f;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
long starting = System.nanoTime();
int w = getWidth();
int h = getHeight();
if((w==0) || (h==0)){
return;
}
float x = (float)w/2.0f;
float y = (float)h/2.0f;
float radius, innerRadius;
if(w > h){
radius = h * ratioRadius;
innerRadius = h * ratioInnerRadius;
}else{
radius = w * ratioRadius;
innerRadius = w * ratioInnerRadius;
}
myShape.setStar(x, y, radius, innerRadius, numberOfPoint);
//Save and rotate canvas
canvas.save();
canvas.rotate(rotate, x, y);
phase++;
PathDashPathEffect pathDashPathEffect =
new PathDashPathEffect(dashPath, 15.0f, phase, PathDashPathEffect.Style.MORPH);
Paint paintDash = myShape.getPaint();
paintDash.setPathEffect(pathDashPathEffect);
canvas.drawPath(myShape.getPath(), myShape.getPaint());
//restore canvas
canvas.restore();
long end = System.nanoTime();
String info = "myView.isHardwareAccelerated() = " + isHardwareAccelerated() + "\n"
+ "canvas.isHardwareAccelerated() = " + canvas.isHardwareAccelerated() + "\n"
+ "processing time (reference only) : " + String.valueOf(end - starting) + " (ns)";
textLayerInfo.setText(info);
invalidate();
}
public void setShapeRadiusRatio(float ratio){
ratioRadius = ratio;
}
public void setShapeInnerRadiusRatio(float ratio){
ratioInnerRadius = ratio;
}
public void setNumberOfPoint(int pt){
numberOfPoint = pt;
}
public void passElements(TextView textLayerInfo){
this.textLayerInfo = textLayerInfo;
}
public void setShapeRotate(int rot){
rotate = (float)rot;
}
}
Other files, refer to last example.
Download the files.
More example of Drawing Path on canvas of custom View.
Sunday, June 15, 2014
Implement WebChromeClient to retrieve downloaded favicon and title in WebView.
In the post of "Create your own App for FIFA World Cup", we use our default icon and title. Now I want to use the downloaded favicon and title from the target page as our icon and title.
To get the downloaded icon and title, implement our custom WebChromeClient, MyWebChromeClient, override onReceivedIcon() and onReceivedTitle() methods.
To update icon and title, call getSupportActionBar().setIcon(iconDrawable) and getSupportActionBar().setTitle(title). In order to call getSupportActionBar(), change our MainActivity extends ActionBarActivity, instead of Activity.
Call myBrowser.setWebChromeClient(new MyWebChromeClient()) in MainActivity to set our custom WebChromeClient.
MainActivity.java
Other files, activity_main.xml, /res/menu/main.xml, /res/values/strings.xml and AndroidManifest.xml, refer to the last post.
Download the files.
To get the downloaded icon and title, implement our custom WebChromeClient, MyWebChromeClient, override onReceivedIcon() and onReceivedTitle() methods.
To update icon and title, call getSupportActionBar().setIcon(iconDrawable) and getSupportActionBar().setTitle(title). In order to call getSupportActionBar(), change our MainActivity extends ActionBarActivity, instead of Activity.
Call myBrowser.setWebChromeClient(new MyWebChromeClient()) in MainActivity to set our custom WebChromeClient.
MainActivity.java
package com.example.myfifa;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public class MyWebChromeClient extends WebChromeClient {
@Override
public void onReceivedTitle(WebView view, String title) {
Toast.makeText(getApplicationContext(),
"Title received: " + title,
Toast.LENGTH_LONG).show();
getSupportActionBar().setTitle(title);
super.onReceivedTitle(view, title);
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
Toast.makeText(getApplicationContext(),
"icon received",
Toast.LENGTH_LONG).show();
BitmapDrawable iconDrawable =
new BitmapDrawable(getResources(), icon);
getSupportActionBar().setIcon(iconDrawable);
super.onReceivedIcon(view, icon);
}
}
WebView myBrowser;
private final static String FIFA_HOME = "http://www.fifa.com/";
private final static String KEY_URL = "KEY_URL";
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//restore url after config/orientation changed
String openUrl = FIFA_HOME;
if (savedInstanceState != null) {
openUrl = savedInstanceState.getString(KEY_URL);
}
myBrowser = (WebView)findViewById(R.id.mybrowser);
myBrowser.getSettings().setJavaScriptEnabled(true);
myBrowser.setWebViewClient(new WebViewClient());
myBrowser.setWebChromeClient(new MyWebChromeClient());
myBrowser.loadUrl(openUrl);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
//save url before config/orientation changed
outState.putString(KEY_URL, myBrowser.getUrl());
super.onSaveInstanceState(outState);
}
@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 boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_openinbrowser) {
Uri openUri = Uri.parse(myBrowser.getUrl());
Intent myIntent = new Intent(Intent.ACTION_VIEW, openUri);
startActivity(myIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
}
Other files, activity_main.xml, /res/menu/main.xml, /res/values/strings.xml and AndroidManifest.xml, refer to the last post.
Download the files.
Saturday, June 14, 2014
Unboxing Android USB: A hands on approach with real world examples
If you are a multimedia developer on Android platform you need USB for media transfer or playback audio. This book explores MTP and USB Audio in both USB device and USB host mode.
If you are an core developer who work on charging you need to understand USB charging specification which is explained in the book,
If you are a networking developer interested in tethering, USB plays a role using RNDIS specification which is explained in the book
If you are an application developer interested in managing USB devices in from an Android platform, this book explores Android USB Service framework which manages USB functionalities
Last not the least, Android Debug Bridge (ADB) the debugging tool of Android is over USB and knowledge of its internals is a define value add for any application or platform developer. This book details the internal of ABD till the kernel level.
Thus this book covers everything about USB on Android from different USB Classes supported in device mode to the USB host framework that manages USB device connected to an Android platform. Each chapter will explain USB class specification before exploring how the functionality (class) is implemented in Android. This gives a clean perspective for you as a reader on what the USB specification demands and how it implemented in Android.
Unboxing Android USB: A hands on approach with real world examples
What you'll learn
If you are an core developer who work on charging you need to understand USB charging specification which is explained in the book,
If you are a networking developer interested in tethering, USB plays a role using RNDIS specification which is explained in the book
If you are an application developer interested in managing USB devices in from an Android platform, this book explores Android USB Service framework which manages USB functionalities
Last not the least, Android Debug Bridge (ADB) the debugging tool of Android is over USB and knowledge of its internals is a define value add for any application or platform developer. This book details the internal of ABD till the kernel level.
Thus this book covers everything about USB on Android from different USB Classes supported in device mode to the USB host framework that manages USB device connected to an Android platform. Each chapter will explain USB class specification before exploring how the functionality (class) is implemented in Android. This gives a clean perspective for you as a reader on what the USB specification demands and how it implemented in Android.
Unboxing Android USB: A hands on approach with real world examples
What you'll learn
- Understand Android USB framework from APIs to the kernel layer and enable advance USB application development.
- Learn all major USB functionalities by exploring the USB Class specification not covered in any of the USB books
- Learn the newly introduced Android Open Accessory (AOA) Protocol and explore developing NFC reader using AOA protocol.
- Learn critical changes in the Android USB framework between different Android versions.
- Learn how USB charging works with explanation from the USB Battery Specification.
- Learn how to switch between MTP to Mass Storage and vice versa to share storage to host PC.
- The primary audiences of this book are application developers and engineers who do hands on work with Android. This book is for an application developer who has an APP idea with USB and wonders how to implement it. This book will be a definite guide for the developer and help him/her to manage USB on Android.
- With the book covering from APIs to the Linux kernel, core platform developers finds it easy to put data point to debug. Thus core Android platform developers working on USB, Audio, media and others are the next primary audiences of the book.
- Technical Managers or Architects or senior managers who look for eagle eye view of a system, are the secondary audiences of the book. The book will enable them to understand the different blocks of the Android USB subsystem and would help plan and estimate complexity involved.
- Student and engineers can use this book as a do it yourself reference book as the book explains different blocks the Android USB framework from application level to the kernel. Students can use similar study approach to similar Android framework.
Friday, June 13, 2014
Add uses-permission of "android.permission.INTERNET" in AndroidManifest.xml.
To grant permission of accessing Internet to your app, edit AndroidManifest.xml and add the code:
<uses-permission android:name="android.permission.INTERNET"/>
Thursday, June 12, 2014
Create your own App for FIFA World Cup
Just a funny exercise to load The Official Website of the FIFA World Cup (http://www.fifa.com/) in a webview.
MainActivity.java
activity_main.xml
Modify /res/menu/main.xml to replace add option item of action_openinbrowser.
Modify /res/values/strings.xml to add string resource of "action_openinbrowser".
uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Download the files.
Download and try the APK.
Next:
- Implement WebChromeClient to retrieve downloaded favicon and title in WebView.
MainActivity.java
package com.example.myfifa;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
WebView myBrowser;
private final static String FIFA_HOME = "http://www.fifa.com/";
private final static String KEY_URL = "KEY_URL";
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//restore url after config/orientation changed
String openUrl = FIFA_HOME;
if (savedInstanceState != null) {
openUrl = savedInstanceState.getString(KEY_URL);
}
myBrowser = (WebView)findViewById(R.id.mybrowser);
myBrowser.getSettings().setJavaScriptEnabled(true);
myBrowser.setWebViewClient(new WebViewClient());
myBrowser.loadUrl(openUrl);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
//save url before config/orientation changed
outState.putString(KEY_URL, myBrowser.getUrl());
super.onSaveInstanceState(outState);
}
@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 boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_openinbrowser) {
Uri openUri = Uri.parse(myBrowser.getUrl());
Intent myIntent = new Intent(Intent.ACTION_VIEW, openUri);
startActivity(myIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
}
activity_main.xml
<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"
tools:context="com.example.myfifa.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<WebView
android:id="@+id/mybrowser"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Modify /res/menu/main.xml to replace add option item of action_openinbrowser.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.myfifa.MainActivity" >
<item
android:id="@+id/action_openinbrowser"
android:orderInCategory="100"
android:title="@string/action_openinbrowser"
app:showAsAction="ifRoom|withText"/>
</menu>
Modify /res/values/strings.xml to add string resource of "action_openinbrowser".
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyFIFA</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="action_openinbrowser">Open in Browser</string>
</resources>
uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Download the files.
Download and try the APK.
Next:
- Implement WebChromeClient to retrieve downloaded favicon and title in WebView.
The Official FIFA World Cup App on Android
The Official FIFA World Cup App
https://play.google.com/store/apps/details?id=com.fifa.fifaapp.android
Download the Official App of the 2014 FIFA World Cup Brazil™, unlocking all the exclusive coverage from the planet's biggest single-sporting event. With the official FIFA World Cup App, you can take the World Cup with you everywhere you go.
https://play.google.com/store/apps/details?id=com.fifa.fifaapp.android
Download the Official App of the 2014 FIFA World Cup Brazil™, unlocking all the exclusive coverage from the planet's biggest single-sporting event. With the official FIFA World Cup App, you can take the World Cup with you everywhere you go.
Wednesday, June 11, 2014
Set opacity/alpha of Button or drawable
Example to change opacity/alpha of Button or its CompoundDrawables, also show how to display CompoundDrawables on Button programmatically.
Example code:
MainActivity.java
activity_main.xml
Example code:
MainActivity.java
package com.example.androidsetimageopacity;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class MainActivity extends Activity {
SeekBar barOpacityButton;
SeekBar barOpacityDrawableLeft, barOpacityDrawableTop,
barOpacityDrawableRight, barOpacityDrawableBottom;
Button button;
Drawable drawableLeft, drawableTop, drawableRight, drawableBottom;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawableLeft = getResources()
.getDrawable(android.R.drawable.ic_menu_call);
drawableTop = getResources()
.getDrawable(android.R.drawable.ic_menu_agenda);
drawableRight = getResources()
.getDrawable(android.R.drawable.ic_menu_compass);
drawableBottom = getResources()
.getDrawable(android.R.drawable.ic_menu_camera);
button = (Button)findViewById(R.id.button);
//display CompoundDrawables on Button programmatically
button.setCompoundDrawablesWithIntrinsicBounds(
drawableLeft, drawableTop, drawableRight, drawableBottom);
barOpacityButton =
(SeekBar)findViewById(R.id.opacitybutton);
barOpacityDrawableLeft =
(SeekBar)findViewById(R.id.opacitydrawableleft);
barOpacityDrawableTop =
(SeekBar)findViewById(R.id.opacitydrawabletop);
barOpacityDrawableRight =
(SeekBar)findViewById(R.id.opacitydrawableright);
barOpacityDrawableBottom =
(SeekBar)findViewById(R.id.opacitydrawablebottom);
barOpacityButton.setOnSeekBarChangeListener(
barOpacityButtonOnSeekBarChangeListener);
barOpacityDrawableLeft.setOnSeekBarChangeListener(
barOpacityDrawableOnSeekBarChangeListener);
barOpacityDrawableTop.setOnSeekBarChangeListener(
barOpacityDrawableOnSeekBarChangeListener);
barOpacityDrawableRight.setOnSeekBarChangeListener(
barOpacityDrawableOnSeekBarChangeListener);
barOpacityDrawableBottom.setOnSeekBarChangeListener(
barOpacityDrawableOnSeekBarChangeListener);
}
OnSeekBarChangeListener barOpacityButtonOnSeekBarChangeListener =
new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
float alpha = (float)progress/(float)seekBar.getMax();
button.setAlpha(alpha); //for API Level 11+
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
OnSeekBarChangeListener barOpacityDrawableOnSeekBarChangeListener =
new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
drawableLeft.setAlpha(
barOpacityDrawableLeft.getProgress());
drawableTop.setAlpha(
barOpacityDrawableTop.getProgress());
drawableRight.setAlpha(
barOpacityDrawableRight.getProgress());
drawableBottom.setAlpha(
barOpacityDrawableBottom.getProgress());
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
}
activity_main.xml
<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: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="com.example.androidsetimageopacity.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<SeekBar
android:id="@+id/opacitybutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="100"/>
<SeekBar
android:id="@+id/opacitydrawableleft"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="255"/>
<SeekBar
android:id="@+id/opacitydrawabletop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="255"/>
<SeekBar
android:id="@+id/opacitydrawableright"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="255"/>
<SeekBar
android:id="@+id/opacitydrawablebottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="255"/>
<TextView
android:id="@+id/opacitysetting"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Opacity Button"/>
</LinearLayout>
Tuesday, June 10, 2014
Change Opacity of ImageView programmatically
Example to change opacity/alpha of ImageView programmatically, by calling deprecated setAlpha(alpha) or setImageAlpha(alpha) for APL Level 16 or higher.
MainActivity.java
activity_main.xml
MainActivity.java
package com.example.androidsetimageopacity;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MainActivity extends Activity {
SeekBar barOpacity;
ImageView image;
TextView textOpacitySetting;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView)findViewById(R.id.image);
textOpacitySetting = (TextView)findViewById(R.id.opacitysetting);
barOpacity = (SeekBar)findViewById(R.id.opacity);
int alpha = barOpacity.getProgress();
textOpacitySetting.setText(String.valueOf(alpha));
image.setAlpha(alpha); //deprecated
//image.setImageAlpha(alpha); //for API Level 16+
barOpacity.setOnSeekBarChangeListener(barOpacityOnSeekBarChangeListener);
}
OnSeekBarChangeListener barOpacityOnSeekBarChangeListener =
new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
int alpha = barOpacity.getProgress();
textOpacitySetting.setText(String.valueOf(alpha));
image.setAlpha(alpha); //deprecated
//image.setImageAlpha(alpha); //for API Level 16+
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
}
activity_main.xml
<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: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="com.example.androidsetimageopacity.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<SeekBar
android:id="@+id/opacity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="511"
android:progress="100"/>
<TextView
android:id="@+id/opacitysetting"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher" />
</LinearLayout>
Use CountDownTimer to do something repeatly, second example.
It is another approach to do the same job as the previous example "Use CountDownTimer to do something repeatly, updating custom view". Instead of implementing CountDownTimer inside custom view as self running function of custom view, this example implement CountDownTimer in MainActivity, and handle all the timing functions. The custom view simple display the graphic only.
MainActivity.java
SpotView.java
Keep using the same layout in previous example.
MainActivity.java
package com.example.androidcountdowntimer;
import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity{
CountDownTimer countDownTimer;
int state;
final static int STATE_IDLE = 0;
final static int STATE_RED = 1;
final static int STATE_GREEN = 2;
final static int STATE_BLUE = 3;
TextView myState, myCounter;
Button btnStart;
SpotView mySpotView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySpotView = (SpotView)findViewById(R.id.myspotview);
myState = (TextView) findViewById(R.id.mystate);
myCounter = (TextView) findViewById(R.id.mycounter);
btnStart = (Button) findViewById(R.id.start);
btnStart.setOnClickListener(btnStartOnClickListener);
state = STATE_IDLE;
}
OnClickListener btnStartOnClickListener =
new OnClickListener(){
@Override
public void onClick(View v) {
if(countDownTimer!=null){
countDownTimer.cancel();
}
state = STATE_RED;
countDownTimer = new CountDownTimer(3000, 500) {
@Override
public void onTick(long millisUntilFinished) {
myCounter.setText("onTick: " + millisUntilFinished);
}
@Override
public void onFinish() {
if(state == STATE_RED){
state = STATE_GREEN;
mySpotView.setSpots(false, true, false);
myState.setText("GREEN");
}else if(state == STATE_GREEN){
state = STATE_BLUE;
mySpotView.setSpots(false, false, true);
myState.setText("BLUE");
}else if(state == STATE_BLUE){
state = STATE_RED;
mySpotView.setSpots(true, false, false);
myState.setText("RED");
}
countDownTimer.start();
}
};
mySpotView.setSpots(true, false, false);
myState.setText("RED");
countDownTimer.start();
}
};
}
SpotView.java
package com.example.androidcountdowntimer;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class SpotView extends View{
boolean spotRedOn, spotGreenOn, spotBlueOn;
Paint paintRed, paintGreen, paintBlue;
public SpotView(Context context) {
super(context);
init();
}
public SpotView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SpotView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
paintRed = new Paint();
paintRed.setColor(Color.RED);
paintRed.setStrokeWidth(1);
paintRed.setStyle(Paint.Style.FILL);
paintGreen = new Paint();
paintGreen.setColor(Color.GREEN);
paintGreen.setStrokeWidth(1);
paintGreen.setStyle(Paint.Style.FILL);
paintBlue = new Paint();
paintBlue.setColor(Color.BLUE);
paintBlue.setStrokeWidth(1);
paintBlue.setStyle(Paint.Style.FILL);
spotRedOn = spotGreenOn = spotBlueOn = false;
}
public void setSpots(boolean r, boolean g, boolean b){
spotRedOn = r;
spotGreenOn = g;
spotBlueOn = b;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
float w = getWidth();
float h = getHeight();
if(spotRedOn){
canvas.drawCircle(w/4, h/2, 100, paintRed);
}
if(spotGreenOn){
canvas.drawCircle(w/2, h/2, 100, paintGreen);
}
if(spotBlueOn){
canvas.drawCircle(3*w/4, h/2, 100, paintBlue);
}
}
}
Keep using the same layout in previous example.
Monday, June 9, 2014
Use CountDownTimer to do something repeatly, updating custom view.
This example show how to change color spots in custom view repeatly with CountDownTimer. We also implement callback interface on MainActivity.java, such that our custom view can callback MainActivity to pass something.
May be it is not a good practice to achieve such a job, just a example to use CountDownTimer.
MainActivity.java
SpotView.java
/res/layout/activity_main.xml
Next example:
- Another approach to handle CountDownTimer in MainActivity, and the custom view handle display only.
May be it is not a good practice to achieve such a job, just a example to use CountDownTimer.
MainActivity.java
package com.example.androidcountdowntimer;
import com.example.androidcountdowntimer.SpotView.SpotCallBack;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity
implements SpotCallBack{
TextView myState, myCounter;
Button btnStart;
SpotView mySpotView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySpotView = (SpotView)findViewById(R.id.myspotview);
mySpotView.setCallback(this);
myState = (TextView) findViewById(R.id.mystate);
myCounter = (TextView) findViewById(R.id.mycounter);
btnStart = (Button) findViewById(R.id.start);
btnStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mySpotView.startRun();
}
});
}
@Override
public void cb_onTick(String msg) {
myCounter.setText("onTick: " + msg);
}
@Override
public void cb_onFinish(String msg) {
myState.setText(msg);
}
}
SpotView.java
package com.example.androidcountdowntimer;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.view.View;
public class SpotView extends View{
//used to pass back something to MainActivity
interface SpotCallBack {
void cb_onTick(String msg);
void cb_onFinish(String msg);
}
SpotCallBack spotCallback;
CountDownTimer countDownTimer;
int state;
final static int STATE_IDLE = 0;
final static int STATE_RED = 1;
final static int STATE_GREEN = 2;
final static int STATE_BLUE = 3;
Paint paintRed, paintGreen, paintBlue;
public SpotView(Context context) {
super(context);
init();
}
public SpotView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SpotView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
state = STATE_IDLE;
paintRed = new Paint();
paintRed.setColor(Color.RED);
paintRed.setStrokeWidth(1);
paintRed.setStyle(Paint.Style.FILL);
paintGreen = new Paint();
paintGreen.setColor(Color.GREEN);
paintGreen.setStrokeWidth(1);
paintGreen.setStyle(Paint.Style.FILL);
paintBlue = new Paint();
paintBlue.setColor(Color.BLUE);
paintBlue.setStrokeWidth(1);
paintBlue.setStyle(Paint.Style.FILL);
}
public void setCallback(SpotCallBack cb){
spotCallback = cb;
}
public void startRun(){
state = STATE_RED;
if(countDownTimer!=null){
countDownTimer.cancel();
}
countDownTimer = new CountDownTimer(3000, 500) {
@Override
public void onTick(long millisUntilFinished) {
spotCallback.cb_onTick(String.valueOf(millisUntilFinished));
}
@Override
public void onFinish() {
if(state == STATE_RED){
state = STATE_GREEN;
spotCallback.cb_onFinish("GREEN");
}else if(state == STATE_GREEN){
state = STATE_BLUE;
spotCallback.cb_onFinish("BLUE");
}else if(state == STATE_BLUE){
state = STATE_RED;
spotCallback.cb_onFinish("RED");
}
countDownTimer.start();
invalidate();
}
};
countDownTimer.start();
spotCallback.cb_onFinish("RED");
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
float w = getWidth();
float h = getHeight();
if(state == STATE_RED){
canvas.drawCircle(w/4, h/2, 100, paintRed);
}else if(state == STATE_GREEN){
canvas.drawCircle(w/2, h/2, 100, paintGreen);
}else if(state == STATE_BLUE){
canvas.drawCircle(3*w/4, h/2, 100, paintBlue);
}
}
}
/res/layout/activity_main.xml
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidcountdowntimer.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<Button
android:id="@+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start CountDownTimer" />
<TextView
android:id="@+id/mystate"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/mycounter"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.example.androidcountdowntimer.SpotView
android:id="@+id/myspotview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Next example:
- Another approach to handle CountDownTimer in MainActivity, and the custom view handle display only.
Saturday, June 7, 2014
Restart CountDownTimer
Refer to my old exercise of "Count Down Timer", it is a one-shot CountDownTimer. In some case you want to reset/restart the CountDownTimer, you have to cancel the old one if exist, otherwise both old and new CountDownTimer will run together.
Example:
MainActivity.java
Next:
- Use CountDownTimer to do something repeatly, updating custom view; handle CountDownTimer in custom view.
- Another approach to use CountDownTimer to do something repeatly; handle CountDownTimer in MainActivity, custom view handle display only.
Example:
MainActivity.java
package com.example.androidcountdowntimer;
import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView myCounter;
Button btnStart;
CountDownTimer countDownTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myCounter = (TextView) findViewById(R.id.mycounter);
btnStart = (Button) findViewById(R.id.start);
btnStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//cancel the old countDownTimer
if(countDownTimer!=null){
countDownTimer.cancel();
}
countDownTimer = new CountDownTimer(10000, 1000) {
@Override
public void onFinish() {
myCounter.setText("Finished!");
}
@Override
public void onTick(long millisUntilFinished) {
myCounter.setText("Millisecond Until Finished: "
+ String.valueOf(millisUntilFinished));
}
};
countDownTimer.start();
}
});
}
}
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidcountdowntimer.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<Button
android:id="@+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start CountDownTimer" />
<TextView
android:id="@+id/mycounter"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Next:
- Use CountDownTimer to do something repeatly, updating custom view; handle CountDownTimer in custom view.
- Another approach to use CountDownTimer to do something repeatly; handle CountDownTimer in MainActivity, custom view handle display only.
Animation follow touch path forward and backward
Further modify the example of "Change speed of Animation follow touch path" to add feature of animation direction, forward and backward.
AnimationView.java
/res/layout/activity_main.xml
MainActivity.java
Download the files.
More example of Drawing Path on canvas of custom View.
AnimationView.java
package com.example.androidanimationalongpath;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class AnimationView extends View {
Paint paint;
Bitmap bm;
int bm_offsetX, bm_offsetY;
Path animPath;
PathMeasure pathMeasure;
float pathLength;
float step; //distance each step
float distance; //distance moved
float curX, curY;
float curAngle; //current angle
float targetAngle; //target angle
float stepAngle; //angle each step
float[] pos;
float[] tan;
Matrix matrix;
Path touchPath;
static int FORWARD = 1;
static int BACKWARD = -1;
int direction;
public AnimationView(Context context) {
super(context);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
public void initMyView(){
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.STROKE);
bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
bm_offsetX = bm.getWidth()/2;
bm_offsetY = bm.getHeight()/2;
animPath = new Path();
pos = new float[2];
tan = new float[2];
matrix = new Matrix();
touchPath = new Path();
step = 1; //default
stepAngle = 1; //default
direction = FORWARD; //default
}
@Override
protected void onDraw(Canvas canvas) {
if(animPath.isEmpty()){
return;
}
canvas.drawPath(animPath, paint);
matrix.reset();
if((targetAngle-curAngle)>stepAngle){
curAngle += stepAngle;
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
invalidate();
}else if((curAngle-targetAngle)>stepAngle){
curAngle -= stepAngle;
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
invalidate();
}else{
curAngle=targetAngle;
if((direction==FORWARD && distance < pathLength)
||(direction==BACKWARD && distance > 0)){
pathMeasure.getPosTan(distance, pos, tan);
targetAngle = (float)(Math.atan2(tan[1], tan[0])*180.0/Math.PI);
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
curX = pos[0]-bm_offsetX;
curY = pos[1]-bm_offsetY;
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
distance += step * direction;
invalidate();
}else{
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
touchPath.reset();
touchPath.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
touchPath.lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
touchPath.lineTo(event.getX(), event.getY());
animPath = new Path(touchPath);
pathMeasure = new PathMeasure(animPath, false);
pathLength = pathMeasure.getLength();
//step = 1;
distance = 0;
curX = 0;
curY = 0;
//stepAngle = 1;
curAngle = 0;
targetAngle = 0;
direction = FORWARD;
invalidate();
break;
}
return true;
}
public void setSpeed(int sp){
step = sp;
stepAngle = sp;
}
public void replayForward(){
direction = FORWARD;
invalidate();
}
public void replayBackward(){
direction = BACKWARD;
invalidate();
}
}
/res/layout/activity_main.xml
<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: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="com.example.androidanimationalongpath.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/replayfor"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Replay/Forward" />
<Button
android:id="@+id/replayback"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Replay/Backward" />
</LinearLayout>
<SeekBar
android:id="@+id/speedbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<com.example.androidanimationalongpath.AnimationView
android:id="@+id/animationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@android:color/darker_gray" />
</LinearLayout>
</LinearLayout>
MainActivity.java
package com.example.androidanimationalongpath;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
AnimationView animationView;
SeekBar speedBar;
Button btnForward, btnbackward;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
animationView = (AnimationView)findViewById(R.id.animationview);
speedBar = (SeekBar)findViewById(R.id.speedbar);
speedBar.setOnSeekBarChangeListener(speedBarOnSeekBarChangeListener);
animationView.setSpeed(speedBar.getProgress()); //set default speed
btnForward = (Button)findViewById(R.id.replayfor);
btnForward.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
animationView.replayForward();
}});
btnbackward = (Button)findViewById(R.id.replayback);
btnbackward.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
animationView.replayBackward();
}});
}
OnSeekBarChangeListener speedBarOnSeekBarChangeListener =
new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
//offset from SeekBar 0~19 to step 1~10
animationView.setSpeed(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
}
Download the files.
More example of Drawing Path on canvas of custom View.
Friday, June 6, 2014
Learning Android Intents
Explore and apply the power of intents in Android application development
Learning Android Intents
Overview
Android is an emerging technology with loads of apps in the Google Play Market. Till date, it is the biggest marvel in Smartphone technology, propelling a larger number of developers into Android application development. Intent is an essential part of any Android Application and no Android application is complete without using them. Features such as listening broadcasts, sending messages, sharing via social networks, notifications, hardware components including camera, sensors, Wi-Fi, and more, can be used in your applications by using Intents.
This practical guide focuses on using intents to make the best use of various features of Android platform. It is ideal for those developers who want to understand the backbone and the domain of Android Intents, its power, and the need for it inside an Android application. Practical, in-depth examples are used throughout the book, to help you understand the key concepts.
The book starts with introducing the very basic concepts of Android, and its various facts and figures such as different Android versions, their release dates, evolution of Android phones and so on. While covering the basic technical concepts, it proceeds from the easiest route of introducing Android Intents towards the more practical view of Android Intents in terms of components and features.
You will learn how to use different components and features such as transfer data between activities, invoke various features and components of Android, execute different in-built and custom-made services, use hardware and software components of Android device, and start Pending Intents & notifications. You will gain better theoretical knowledge of what is running behind the concepts of Android Intents, and practical knowledge of the mobile-efficient ways to perform a certain task using Android Intents.
Towards the end, you will have a clear vision and a practical grip on Android intents and its features. Learning Android Intents is a proper guide to give you the best knowledge of Intents.
What you will learn from this book
The book will take an easy-to-follow and engaging tutorial approach, providing a practical and comprehensive way to learn Android intents.
Overview
- Understand Android Intents to make application development quicker and easier
- Categorize and implement various kinds of Intents in your application
- Perform data manipulation within Android applications
Android is an emerging technology with loads of apps in the Google Play Market. Till date, it is the biggest marvel in Smartphone technology, propelling a larger number of developers into Android application development. Intent is an essential part of any Android Application and no Android application is complete without using them. Features such as listening broadcasts, sending messages, sharing via social networks, notifications, hardware components including camera, sensors, Wi-Fi, and more, can be used in your applications by using Intents.
This practical guide focuses on using intents to make the best use of various features of Android platform. It is ideal for those developers who want to understand the backbone and the domain of Android Intents, its power, and the need for it inside an Android application. Practical, in-depth examples are used throughout the book, to help you understand the key concepts.
The book starts with introducing the very basic concepts of Android, and its various facts and figures such as different Android versions, their release dates, evolution of Android phones and so on. While covering the basic technical concepts, it proceeds from the easiest route of introducing Android Intents towards the more practical view of Android Intents in terms of components and features.
You will learn how to use different components and features such as transfer data between activities, invoke various features and components of Android, execute different in-built and custom-made services, use hardware and software components of Android device, and start Pending Intents & notifications. You will gain better theoretical knowledge of what is running behind the concepts of Android Intents, and practical knowledge of the mobile-efficient ways to perform a certain task using Android Intents.
Towards the end, you will have a clear vision and a practical grip on Android intents and its features. Learning Android Intents is a proper guide to give you the best knowledge of Intents.
What you will learn from this book
- Understand Android Intents and their importance in Android apps
- Get to grips with the different types of Intents and their implementation
- Discover data transfer methods in Android Intents along with their optimization and performance comparisons
- Explore the implementation of Intents while invoking Android Features in an application.
- Use Intent Filters and their sub-domains in order to perform various actions and sorting categories in Android Intents
- Catch different events while working with Broadcast Receiver and perform various actions
- Implement pending Intents and Intent Service, sending text to the Notification Panel, and much more
The book will take an easy-to-follow and engaging tutorial approach, providing a practical and comprehensive way to learn Android intents.
Change speed of Animation follow touch path
This exercise change the speed of the former example of "Animation follow touch path".
AnimationView.java
/res/layout/activity_main.xml
MainActivity.java
Download the files.
More example of Drawing Path on canvas of custom View.
- The speed is base on the approximate frame-per-second of 60, read "Know the performance, timing and speed of animation".
- When the speed, set in SeekBar, is 0, the animation will stay here.
AnimationView.java
package com.example.androidanimationalongpath;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class AnimationView extends View {
Paint paint;
Bitmap bm;
int bm_offsetX, bm_offsetY;
Path animPath;
PathMeasure pathMeasure;
float pathLength;
float step; //distance each step
float distance; //distance moved
float curX, curY;
float curAngle; //current angle
float targetAngle; //target angle
float stepAngle; //angle each step
float[] pos;
float[] tan;
Matrix matrix;
Path touchPath;
public AnimationView(Context context) {
super(context);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
public void initMyView(){
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.STROKE);
bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
bm_offsetX = bm.getWidth()/2;
bm_offsetY = bm.getHeight()/2;
animPath = new Path();
pos = new float[2];
tan = new float[2];
matrix = new Matrix();
touchPath = new Path();
step = 1; //default
stepAngle = 1; //default
}
@Override
protected void onDraw(Canvas canvas) {
if(animPath.isEmpty()){
return;
}
canvas.drawPath(animPath, paint);
matrix.reset();
if((targetAngle-curAngle)>stepAngle){
curAngle += stepAngle;
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
invalidate();
}else if((curAngle-targetAngle)>stepAngle){
curAngle -= stepAngle;
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
invalidate();
}else{
curAngle=targetAngle;
if(distance < pathLength){
pathMeasure.getPosTan(distance, pos, tan);
targetAngle = (float)(Math.atan2(tan[1], tan[0])*180.0/Math.PI);
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
curX = pos[0]-bm_offsetX;
curY = pos[1]-bm_offsetY;
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
distance += step;
invalidate();
}else{
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
touchPath.reset();
touchPath.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
touchPath.lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
touchPath.lineTo(event.getX(), event.getY());
animPath = new Path(touchPath);
pathMeasure = new PathMeasure(animPath, false);
pathLength = pathMeasure.getLength();
//step = 1;
distance = 0;
curX = 0;
curY = 0;
//stepAngle = 1;
curAngle = 0;
targetAngle = 0;
invalidate();
break;
}
return true;
}
public void setSpeed(int sp){
step = sp;
stepAngle = sp;
}
}
/res/layout/activity_main.xml
<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: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="com.example.androidanimationalongpath.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<SeekBar
android:id="@+id/speedbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<com.example.androidanimationalongpath.AnimationView
android:id="@+id/animationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@android:color/darker_gray" />
</LinearLayout>
</LinearLayout>
MainActivity.java
package com.example.androidanimationalongpath;
import android.support.v7.app.ActionBarActivity;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
AnimationView animationView;
SeekBar speedBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
animationView = (AnimationView)findViewById(R.id.animationview);
speedBar = (SeekBar)findViewById(R.id.speedbar);
speedBar.setOnSeekBarChangeListener(speedBarOnSeekBarChangeListener);
animationView.setSpeed(speedBar.getProgress()); //set default speed
}
OnSeekBarChangeListener speedBarOnSeekBarChangeListener =
new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
//offset from SeekBar 0~19 to step 1~10
animationView.setSpeed(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}};
}
Download the files.
More example of Drawing Path on canvas of custom View.
Xamarin Mobile Application Development for Android
Learn to develop full featured Android apps using your existing C# skills with Xamarin.Android
Xamarin Mobile Application Development for Android
Overview
Technology trends come and go, but few have generated the excitement, momentum, or long-term impact that mobile computing has. Mobile computing impacts people's lives at work and at home on a daily basis. Many companies and individual developers are looking to become a part of the movement but are unsure how to best utilize their existing skills and assets. The Xamarin suite of products provides new opportunities to those who already have a significant investment in C# development skills and .NET code bases, and would like to enter into this new, exciting world.
This example-oriented guide provides a practical approach to quickly learning the fundamentals of Android app development using C# and Xamarin.Android. It will lead the readers through building an Android app step-by-step with steadily increasing complexity.
This book begins with an overview of the Android and Xamarin platforms to provide you with a solid understanding of the environment you will be working in. You will then be gradually walked through building and testing an Android app using C# and the Xamarin.Android product. You will learn the basics of interacting with some of the more interesting aspects of Android devices including location services, the camera, and maps. You will also be given the opportunity to work with three different layout managers to gain an understanding of the various options available for arranging controls and content. The book ends with a discussion on the final steps involved in preparing apps for deployment to the various Android app stores.
In a relatively short period of time, developers familiar with C# and rich client technologies such as WPF and Silverlight will be effectively developing, testing, and delivering Android apps.
What you will learn from this book
A step-by-step tutorial that follows the development of a simple Android app from end to end, through troubleshooting, and then distribution. The language used assumes a knowledge of basic C#.
Who this book is written for
If you are a C# developer with a desire to develop Android apps and want to enhance your existing skill set, then this book is for you. It is assumed that you have a good working knowledge of C#, .NET, and object-oriented software development. Familiarity with rich client technologies such as WPF or Silverlight is also helpful, but not required.
Overview
- Gain an understanding of both the Android and Xamarin platforms
- Build a working multi-view Android app incrementally throughout the book
- Work with device capabilities such as location sensors and the camera
Technology trends come and go, but few have generated the excitement, momentum, or long-term impact that mobile computing has. Mobile computing impacts people's lives at work and at home on a daily basis. Many companies and individual developers are looking to become a part of the movement but are unsure how to best utilize their existing skills and assets. The Xamarin suite of products provides new opportunities to those who already have a significant investment in C# development skills and .NET code bases, and would like to enter into this new, exciting world.
This example-oriented guide provides a practical approach to quickly learning the fundamentals of Android app development using C# and Xamarin.Android. It will lead the readers through building an Android app step-by-step with steadily increasing complexity.
This book begins with an overview of the Android and Xamarin platforms to provide you with a solid understanding of the environment you will be working in. You will then be gradually walked through building and testing an Android app using C# and the Xamarin.Android product. You will learn the basics of interacting with some of the more interesting aspects of Android devices including location services, the camera, and maps. You will also be given the opportunity to work with three different layout managers to gain an understanding of the various options available for arranging controls and content. The book ends with a discussion on the final steps involved in preparing apps for deployment to the various Android app stores.
In a relatively short period of time, developers familiar with C# and rich client technologies such as WPF and Silverlight will be effectively developing, testing, and delivering Android apps.
What you will learn from this book
- Build a multi-view Android application with navigation
- Utilize the ActionBar for app actions
- Create a simple JSON-based persistent service to save data locally on the device
- Lay out content using the LinearLayout, RelativeLayout, and TableLayout layout managers
- Use a ListView (AdapterView) and Adapter to build a view that is populated by dynamic data
- Capture the current location of a device and determine the street address
- Integrate with the map app to display a point of interest
- Capture and save a photo
- Test, debug, and deploy an Android app
A step-by-step tutorial that follows the development of a simple Android app from end to end, through troubleshooting, and then distribution. The language used assumes a knowledge of basic C#.
Who this book is written for
If you are a C# developer with a desire to develop Android apps and want to enhance your existing skill set, then this book is for you. It is assumed that you have a good working knowledge of C#, .NET, and object-oriented software development. Familiarity with rich client technologies such as WPF or Silverlight is also helpful, but not required.