الثلاثاء، 29 أبريل 2014

A good tutorial for Navigation Drawer

The navigation drawer is a panel that displays the app’s main navigation options on the left edge of the screen. It is hidden most of the time, but is revealed when the user swipes a finger from the left edge of the screen or, while at the top level of the app, the user touches the app icon in the action bar.

With navigation drawer, you can easily develop app with YouTube or Google+ apps like navigation.

It's a very good, must see, tutorial of Creating a Navigation Drawer.


الأحد، 27 أبريل 2014

Set text size and color of PagerTitleStrip on ViewPager

Previous example show how to Implement PagerTitleStrip on ViewPager. In the onCreate() method, we get view of PagerTitleStrip (pagerTitleStrip) without using it. We can set text size and color of the PagerTitleStrip by calling its setTextSize() and setTextColor() methods.

Example:
  PagerTitleStrip pagerTitleStrip = (PagerTitleStrip)findViewById(R.id.titlestrip);
pagerTitleStrip.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24);
pagerTitleStrip.setTextColor(Color.BLUE);

on tablet

on phone

Communication between Android using NFC to send text

This example send text between Android devices using NFC. Modify from last post of sending Uri between Android devices using NFC.


Modify AndroidManifest.xml include <intent-filter> of "android.nfc.action.NDEF_DISCOVERED".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidnfc"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.NFC"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidnfc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>

</activity>
</application>

</manifest>

MainActivity.java
package com.example.androidnfc;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements
CreateNdefMessageCallback, OnNdefPushCompleteCallback{

TextView textInfo;
EditText textOut;

NfcAdapter nfcAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInfo = (TextView)findViewById(R.id.info);
textOut = (EditText)findViewById(R.id.textout);

nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(nfcAdapter==null){
Toast.makeText(MainActivity.this,
"nfcAdapter==null, no NFC adapter exists",
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"Set Callback(s)",
Toast.LENGTH_LONG).show();
nfcAdapter.setNdefPushMessageCallback(this, this);
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
}

@Override
protected void onResume() {
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED)){
Parcelable[] parcelables =
intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
textInfo.setText(inMsg);
}
}

@Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
}

@Override
public void onNdefPushComplete(NfcEvent event) {

final String eventString = "onNdefPushComplete\n" + event.toString();
runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(getApplicationContext(),
eventString,
Toast.LENGTH_LONG).show();
}
});

}

@Override
public NdefMessage createNdefMessage(NfcEvent event) {

String stringOut = textOut.getText().toString();
byte[] bytesOut = stringOut.getBytes();

NdefRecord ndefRecordOut = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
bytesOut);

NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
return ndefMessageout;
}

}

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.androidnfc.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" />

<EditText
android:id="@+id/textout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

download filesDownload the files.

السبت، 26 أبريل 2014

AudioRecord and AudioTrack, and to implement voice changer

This example show how to use android.media.AudioRecord and android.media.AudioTrack, to record and playback audio. And also show how to implement voice changer by recording and playing audio in different sampling frequency. (Actually, it is almost same as my old example)


AndroidAudioRecordActivity.java
package com.exercise.AndroidAudioRecord;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;

public class AndroidAudioRecordActivity extends Activity {

String[] freqText = {"11.025 KHz (Lowest)", "16.000 KHz", "22.050 KHz", "44.100 KHz (Highest)"};
Integer[] freqset = {11025, 16000, 22050, 44100};
private ArrayAdapter<String> adapter;

Spinner spFrequency;
Button startRec, stopRec, playBack;

Boolean recording;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startRec = (Button)findViewById(R.id.startrec);
stopRec = (Button)findViewById(R.id.stoprec);
playBack = (Button)findViewById(R.id.playback);

startRec.setOnClickListener(startRecOnClickListener);
stopRec.setOnClickListener(stopRecOnClickListener);
playBack.setOnClickListener(playBackOnClickListener);

spFrequency = (Spinner)findViewById(R.id.frequency);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, freqText);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spFrequency.setAdapter(adapter);

stopRec.setEnabled(false);
}

OnClickListener startRecOnClickListener
= new OnClickListener(){

@Override
public void onClick(View arg0) {

Thread recordThread = new Thread(new Runnable(){

@Override
public void run() {
recording = true;
startRecord();
}

});

recordThread.start();
startRec.setEnabled(false);
stopRec.setEnabled(true);

}};

OnClickListener stopRecOnClickListener
= new OnClickListener(){

@Override
public void onClick(View arg0) {
recording = false;
startRec.setEnabled(true);
stopRec.setEnabled(false);
}};

OnClickListener playBackOnClickListener
= new OnClickListener(){

@Override
public void onClick(View v) {
playRecord();
}

};

private void startRecord(){

File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");

int selectedPos = spFrequency.getSelectedItemPosition();
int sampleFreq = freqset[selectedPos];

final String promptStartRecord =
"startRecord()\n"
+ file.getAbsolutePath() + "\n"
+ (String)spFrequency.getSelectedItem();

runOnUiThread(new Runnable(){

@Override
public void run() {
Toast.makeText(AndroidAudioRecordActivity.this,
promptStartRecord,
Toast.LENGTH_LONG).show();
}});

try {
file.createNewFile();

OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);

int minBufferSize = AudioRecord.getMinBufferSize(sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);

short[] audioData = new short[minBufferSize];

AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);

audioRecord.startRecording();

while(recording){
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for(int i = 0; i < numberOfShort; i++){
dataOutputStream.writeShort(audioData[i]);
}
}

audioRecord.stop();
dataOutputStream.close();

} catch (IOException e) {
e.printStackTrace();
}

}

void playRecord(){

File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");

int shortSizeInBytes = Short.SIZE/Byte.SIZE;

int bufferSizeInBytes = (int)(file.length()/shortSizeInBytes);
short[] audioData = new short[bufferSizeInBytes];

try {
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);

int i = 0;
while(dataInputStream.available() > 0){
audioData[i] = dataInputStream.readShort();
i++;
}

dataInputStream.close();

int selectedPos = spFrequency.getSelectedItemPosition();
int sampleFreq = freqset[selectedPos];

final String promptPlayRecord =
"PlayRecord()\n"
+ file.getAbsolutePath() + "\n"
+ (String)spFrequency.getSelectedItem();

Toast.makeText(AndroidAudioRecordActivity.this,
promptPlayRecord,
Toast.LENGTH_LONG).show();

AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSizeInBytes,
AudioTrack.MODE_STREAM);

audioTrack.play();
audioTrack.write(audioData, 0, bufferSizeInBytes);


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

}

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" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Sampling Frequency" />
<Spinner
android:id = "@+id/frequency"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/startrec"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start Recording" />
<Button
android:id="@+id/stoprec"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Stop Recording" />
<Button
android:id="@+id/playback"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Play Back" />

</LinearLayout>

Permission of "android.permission.RECORD_AUDIO" and "android.permission.WRITE_EXTERNAL_STORAGE" are needed in AndroidManifest.xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidAudioRecord"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".AndroidAudioRecordActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

download filesDownload the files.

Download and try the APK HERE.

Run multi AsyncTask at the same time

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.

~ reference: AsyncTask | Android Developers



This example show how to execute multi AsyncTask at the same in parallel, by calling executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) for (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB), in our StartAsyncTaskInParallel() method. The first three ProgressBars updated by AsyncTask execute in normal approach by calling execute(), the last two ProgressBar updated by AsyncTask execute in parallel.


MainActivity.java
package com.example.androidparallelasynctask;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;

public class MainActivity extends Activity {

public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

ProgressBar myProgressBar;

public MyAsyncTask(ProgressBar target) {
myProgressBar = target;
}

@Override
protected Void doInBackground(Void... params) {
for(int i=0; i<100; i++){
publishProgress(i);
SystemClock.sleep(100);
}
return null;
}

@Override
protected void onProgressUpdate(Integer... values) {
myProgressBar.setProgress(values[0]);
}

}

Button buttonStart;
ProgressBar progressBar1, progressBar2, progressBar3, progressBar4, progressBar5;
MyAsyncTask asyncTask1, asyncTask2, asyncTask3, asyncTask4, asyncTask5;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar1 = (ProgressBar)findViewById(R.id.progressbar1);
progressBar2 = (ProgressBar)findViewById(R.id.progressbar2);
progressBar3 = (ProgressBar)findViewById(R.id.progressbar3);
progressBar4 = (ProgressBar)findViewById(R.id.progressbar4);
progressBar5 = (ProgressBar)findViewById(R.id.progressbar5);

buttonStart = (Button)findViewById(R.id.start);
buttonStart.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
asyncTask1 = new MyAsyncTask(progressBar1);
asyncTask1.execute();
asyncTask2 = new MyAsyncTask(progressBar2);
asyncTask2.execute();
asyncTask3 = new MyAsyncTask(progressBar3);
asyncTask3.execute();
asyncTask4 = new MyAsyncTask(progressBar4);
StartAsyncTaskInParallel(asyncTask4);
asyncTask5 = new MyAsyncTask(progressBar5);
StartAsyncTaskInParallel(asyncTask5);
}});

}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void StartAsyncTaskInParallel(MyAsyncTask task) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
task.execute();
}

}

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.androidparallelasynctask.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"/>

<ProgressBar
android:id="@+id/progressbar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0" />
<ProgressBar
android:id="@+id/progressbar2"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0" />
<ProgressBar
android:id="@+id/progressbar3"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0" />
<ProgressBar
android:id="@+id/progressbar4"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0" />
<ProgressBar
android:id="@+id/progressbar5"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0" />

</LinearLayout>

This video show how it run on devices running various Android version, include:
- Nexus 7 (1st generation), Android 4.4.2
- HTC One X, Android 4.2.2
- HTC Flyer, Android 3.2.1
- Nexus One, Android 2.3.6


download filesDownload the files.

الجمعة، 25 أبريل 2014

Implement PagerTitleStrip on ViewPager

PagerTitleStrip is a non-interactive indicator of the current, next, and previous pages of a ViewPager. It is intended to be used as a child view of a ViewPager widget.

This example modify from last example.


Modify activity_main.xml, add PagerTitleStrip as a child view of a ViewPager.
<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.androidviewpagerapp.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" />

<android.support.v4.view.ViewPager
android:id="@+id/myviewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.PagerTitleStrip
android:id="@+id/titlestrip"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</android.support.v4.view.ViewPager>

</LinearLayout>

Modify MainActivity.java, override getPageTitle() method in MyPagerAdapter to return CharSequence of PageTitle.
package com.example.androidviewpagerapp;

import android.support.v4.view.PagerAdapter;
import android.support.v4.view.PagerTitleStrip;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;

public class MainActivity extends Activity {

ViewPager viewPager;
MyPagerAdapter myPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.myviewpager);
myPagerAdapter = new MyPagerAdapter();
viewPager.setAdapter(myPagerAdapter);

PagerTitleStrip pagerTitleStrip = (PagerTitleStrip)findViewById(R.id.titlestrip);

}

private class MyPagerAdapter extends PagerAdapter{

int NumberOfPages = 5;

int[] res = {
android.R.drawable.ic_dialog_alert,
android.R.drawable.ic_menu_camera,
android.R.drawable.ic_menu_compass,
android.R.drawable.ic_menu_directions,
android.R.drawable.ic_menu_gallery};
int[] backgroundcolor = {
0xFF101010,
0xFF202020,
0xFF303030,
0xFF404040,
0xFF505050};

String[] title = {
"Page 1",
"pAge 2",
"paGe 3",
"pagE 4",
"page 5"};

@Override
public int getCount() {
return NumberOfPages;
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}

@Override
public Object instantiateItem(ViewGroup container, int position) {


TextView textView = new TextView(MainActivity.this);
textView.setTextColor(Color.WHITE);
textView.setTextSize(30);
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setText(String.valueOf(position));

ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(res[position]);
LayoutParams imageParams = new LayoutParams(
LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(imageParams);

LinearLayout layout = new LinearLayout(MainActivity.this);
layout.setOrientation(LinearLayout.VERTICAL);
LayoutParams layoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
layout.setBackgroundColor(backgroundcolor[position]);
layout.setLayoutParams(layoutParams);
layout.addView(textView);
layout.addView(imageView);

final int page = position;
layout.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,
"Page " + page + " clicked",
Toast.LENGTH_LONG).show();
}});

container.addView(layout);
return layout;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout)object);
}

@Override
public CharSequence getPageTitle(int position) {
return title[position];
}

}

}




download filesDownload the files.

- How to Set text size and color of PagerTitleStrip

الخميس، 24 أبريل 2014

Example of ViewPager with custom PagerAdapter

This example show how to implement ViewPager with custom PagerAdapter. (Another example(s) implement ViewPager with FragmentPagerAdapter, read HERE)


Modify activity_main.xml to include android.support.v4.view.ViewPager in layout.
<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.androidviewpagerapp.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" />

<android.support.v4.view.ViewPager
android:id="@+id/myviewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</LinearLayout>

MainActivity.java
package com.example.androidviewpagerapp;

import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;

public class MainActivity extends Activity {

ViewPager viewPager;
MyPagerAdapter myPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.myviewpager);
myPagerAdapter = new MyPagerAdapter();
viewPager.setAdapter(myPagerAdapter);

}

private class MyPagerAdapter extends PagerAdapter{

int NumberOfPages = 5;

int[] res = {
android.R.drawable.ic_dialog_alert,
android.R.drawable.ic_menu_camera,
android.R.drawable.ic_menu_compass,
android.R.drawable.ic_menu_directions,
android.R.drawable.ic_menu_gallery};
int[] backgroundcolor = {
0xFF101010,
0xFF202020,
0xFF303030,
0xFF404040,
0xFF505050};

@Override
public int getCount() {
return NumberOfPages;
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}

@Override
public Object instantiateItem(ViewGroup container, int position) {


TextView textView = new TextView(MainActivity.this);
textView.setTextColor(Color.WHITE);
textView.setTextSize(30);
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setText(String.valueOf(position));

ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(res[position]);
LayoutParams imageParams = new LayoutParams(
LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(imageParams);

LinearLayout layout = new LinearLayout(MainActivity.this);
layout.setOrientation(LinearLayout.VERTICAL);
LayoutParams layoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
layout.setBackgroundColor(backgroundcolor[position]);
layout.setLayoutParams(layoutParams);
layout.addView(textView);
layout.addView(imageView);

final int page = position;
layout.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,
"Page " + page + " clicked",
Toast.LENGTH_LONG).show();
}});

container.addView(layout);
return layout;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout)object);
}

}

}


download filesDownload the files.

Next:
Implement PagerTitleStrip on ViewPager
Implement OnPageChangeListener for ViewPager to monitor the current visible page

الأربعاء، 23 أبريل 2014

Java Programming for Android Developers For Dummies

Get started creating Android apps with Java in no time!

Java Programming for Android Developers For Dummies

The demand for Android apps is not slowing down but many mobile developers who want to create Android apps lack the necessary Java background. This beginner guide gets you up and running with using Java to create Android apps with no prior knowledge or experienced necessary!
  • Shows you the basic Java development concepts and techniques that are necessary to develop Android apps
  • Explores what goes into creating an Android app to give you a better understanding of the various elements
  • Addresses how to deal with standard programming challenges and debugging
Beginning Android Programming with Java For Dummies puts you well on your way toward creating Android apps quickly with Java.

Android Hacker's Handbook

The first comprehensive guide to discovering and preventing attacks on the Android OS

Android Hacker's Handbook

As the Android operating system continues to increase its share of the smartphone market, smartphone hacking remains a growing threat. Written by experts who rank among the world's foremost Android security researchers, this book presents vulnerability discovery, analysis, and exploitation tools for the good guys. Following a detailed explanation of how the Android OS works and its overall security architecture, the authors examine how vulnerabilities can be discovered and exploits developed for various system components, preparing you to defend against them.

If you are a mobile device administrator, security researcher, Android app developer, or consultant responsible for evaluating Android security, you will find this guide is essential to your toolbox.
  • A crack team of leading Android security researchers explain Android security risks, security design and architecture, rooting, fuzz testing, and vulnerability analysis
  • Covers Android application building blocks and security as well as debugging and auditing Android apps
  • Prepares mobile device administrators, security researchers, Android app developers, and security consultants to defend Android systems against attack
Android Hacker's Handbook is the first comprehensive resource for IT professionals charged with smartphone security.

الأحد، 20 أبريل 2014

Example of programming Android NFC

This example send Uri between Android devices using NFC.


To using NFC on your Android app, modify AndroidManifest.xml.
  • This example target minSdkVersion="16"
  • Add permission of "android.permission.NFC"
  • Add intent-filter of "android.nfc.action.NDEF_DISCOVERED"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidnfc"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.NFC"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidnfc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"
android:host="android-er.blogspot.com"
android:pathPrefix="/" />
</intent-filter>

</activity>
</application>

</manifest>


MainActivity.java
package com.example.androidnfc;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements
CreateNdefMessageCallback, OnNdefPushCompleteCallback{

TextView textInfo;

NfcAdapter nfcAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInfo = (TextView)findViewById(R.id.info);

nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(nfcAdapter==null){
Toast.makeText(MainActivity.this,
"nfcAdapter==null, no NFC adapter exists",
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"Set Callback(s)",
Toast.LENGTH_LONG).show();
nfcAdapter.setNdefPushMessageCallback(this, this);
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
}

@Override
protected void onResume() {
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED)){
Parcelable[] parcelables =
intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
textInfo.setText(inMsg);
}
}

@Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
}

@Override
public void onNdefPushComplete(NfcEvent event) {

final String eventString = "onNdefPushComplete\n" + event.toString();
runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(getApplicationContext(),
eventString,
Toast.LENGTH_LONG).show();
}
});

}

@Override
public NdefMessage createNdefMessage(NfcEvent event) {
NdefRecord rtdUriRecord = NdefRecord.createUri("http://android-er.blogspot.com/");

NdefMessage ndefMessageout = new NdefMessage(rtdUriRecord);
return ndefMessageout;
}

}


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.androidnfc.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:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>


download filesDownload the files.

Related:
Communication between Android using NFC to send text

Motorola deve lançar novos aparelhos de entrada no Brasil

A novidade virá em três versões, sendo uma com apenas um chip, uma dual SIM e outra com dois chips e TV digital


Além de estar se preparando para o lançamento ainda este ano de seu novo smartphone top de linha, o Moto X+1, a Motorola parece prestes a introduzir novos aparelhos de entrada. As três versões do dispositivo são conhecidas pelos nomes de modelo XT1021 (com um cartão SIM), XT1022 (compatível com dois chips) e XT1025 (dual SIM com TV digital).

De acordo com uma fotografia revelada por fontes internas da fabricante ao Tecnoblog, os novos celulares de baixo custo devem contar com uma tela de 4,3 polegadas, processador dual-core de 1,2 GHz, 1 GB de RAM e 4 GB de armazenamento interno. Até o momento, não se sabe qual será a resolução do display e nem se será possível expandir a capacidade da memória do gadget por meio de cartões microSD ou portas USB OTG.

Além disso, os smartphones devem contar com câmera traseira de 5 MP (sem frontal), Mp3 player, rádio FM, bateria de 1.900 mAh e Android 4.4 KitKat de fábrica. Os dispositivos não serão compatíveis com as redes 4G, ficando limitados ao 3G e 2G. Segundo a imagem divulgada, o modelo com TV digital terá preço sugerido de R$ 599, o que significa que as duas outras versões devem custar ainda menos.


Especificações técnicas

- Tela: display de 4,3polegadas;
- CPU: processador dual-core de 1,2 GHz;
- Memória: 1 GB de RAM;
- Armazenamento interno: 4 GB;
- Câmera: traseira de 5 MP (sem frontal);
- Conectividades: Bluetooth, 2G e 3G;
- Bateria: 1.900 mAh;
- SIM: versões com compatibilidade para um (XT1021) e dois chips (XT1022 e XT1025);
- Sistema operacional: Android 4.4 KitKat de fábrica;
- Recursos adicionais: TV digital (somente no modelo XT1025), MP3 e player, rádio FM;
- Dimensões (A x L x E): aproximadamente 12,5 x 6,5 x 0,6 cm.


As três variantes já foram homologadas pela Anatel e devem ser lançadas já em maio, mas as fotos externas e os manuais dos usuários parecem ter sido omitidos pela agência a pedido da Motorola. As fontes dentro da fabricante também comentaram sobre um possível novo modelo do Moto G, que seria compatível com as redes 4G – uma ótima ideia, agora que as operadoras brasileiras estão liberando a tecnologia para os planos pré-pagos.

السبت، 19 أبريل 2014

Strategies for Developing Cross-Device Applications with Visual Studio 2013

This session will cover the strategic decisions developers have to make when targeting multiples devices in application. The video will explore the tools and technologies that available in Visual Studio 2013 for both web and native applications that target Windows, iOS and Android devices, as well as best practices to reuse code and skills across them.

source: http://channel9.msdn.com/Events/Build/2014/2-586

الجمعة، 18 أبريل 2014

What's Google got to do with games?

Video from Google Developers Summit keynote, connecting you with the gaming community. How to use Google's latest technologies to build, distribute, promote, and monetize your games.


الخميس، 17 أبريل 2014

الأربعاء، 16 أبريل 2014

Remote access shared computer using Chrome Remote Desktop app on Android

[Updated@2015-09-09: check the updated post "Remote control Windows 10 from Android using Chrome Remote Desktop"]

The video show how to setup Chrome Remote Desktop on shared computer (running Windows 8.1) to enable remote access with PIN. Then you can control your computer remotely using Chrome Remote Desktop App on Android device.


In shared computer, Windows 8.1 in this example:
  • You need to log-in with a Google account.
  • Install Chrome Remote Desktop in Google Chrome.
  • Run the Chrome Remote Desktop App in Chrome's App pane.
  • Click the Get Started button in "My Computer" box.
  • Click "Enable remote connection".
  • Enter and re-enter the PIN you want, then OK.
  • You will be ask to grant permission by Windows.
  • Your computer, win-8b in this example, will be shown in "My Computer" box.
In Android:
  • Simple install Chrome Remote Desktop App.
  • Run it and select the same Google account in computer side.
  • You can see the computer, win-8b, in the list.

The following video show remote control shared PC from Android Phone. In this example, the Android phone connect Internet using 3G network. The shared PC running Windows 8.1, with Chrome Remote Desktop installed and setup "Enable remote connection", power-on with internet connection (via home network), even have not log-in Windows session, no any port forwarding setting on router. 



You can also access your shared Windows from Ubuntu Linux, read next post "Remote control Windows from Ubuntu Linux with Chrome Remote Desktop".

Related: Share computer desktop with Chrome Remote Desktop


Share computer desktop with Chrome Remote Desktop

Chrome Remote Desktop allows users to remotely access another computer through Chrome browser or a Chromebook.  Computers can be made available on an short-term basis for scenarios such as ad hoc remote support, or on a more long-term basis for remote access to your applications and files.  All connections are fully secured.

Chrome Remote Desktop is fully cross-platform.  Provide remote assistance to Windows, Mac and Linux users, or access your Windows (XP and above) and Mac (OS X 10.6 and above) desktops at any time, all from the Chrome browser on virtually any device, including Chromebooks.

This video show installation and setup Chrome Remote Desktop on Windows 8.1 to be shared. And install and setup on Ubuntu to access the shared Windows desktop.



Related: Access shared computer using Chrome Remote Desktop app on Android

الثلاثاء، 15 أبريل 2014

Display currency symbols

This example TRY to show various available currency symbols on Android. This symbols reference to the file http://www.unicode.org/charts/PDF/U20A0.pdf, it contains an excerpt from the character code tables and list of character names for The Unicode Standard, Version 6.3.

Please note that some symbols cannot be shown, because it have not been installed in Android system.


MainActivity.java
package com.example.androidshowcurrency;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;

public class MainActivity extends Activity {

MyCurrency[] MyCurrencyAll ={
new MyCurrency("$", "dollar sign"),
new MyCurrency("¢", "cent sign"),
new MyCurrency("£", "pound sign"),
new MyCurrency("¤", "currency sign"),
new MyCurrency("¥", "yen sign"),
new MyCurrency("ƒ", "latin small letter f with hook"),
new MyCurrency("", "afghani sign"),
new MyCurrency("৲", "bengali rupee mark"),
new MyCurrency("૱", "gujarati rupee sign"),
new MyCurrency("௹", "tamil rupee sign"),
new MyCurrency("฿", "thai currency symbol baht"),
new MyCurrency("¤", "khmer currency symbol riel"),
new MyCurrency("ℳ", "script capital m"),
new MyCurrency("元", "cjk unified ideograph-5143"),
new MyCurrency("円", "cjk unified ideograph-5186"),
new MyCurrency("圆", "cjk unified ideograph-5706"),
new MyCurrency("圓", "cjk unified ideograph-5713"),
new MyCurrency("", "rial sign"),
new MyCurrency("₠", "EURO-CURRENCY SIGN"),
new MyCurrency("₡", "COLON SIGN"),
new MyCurrency("₢", "CRUZEIRO SIGN"),
new MyCurrency("₣", "FRENCH FRANC SIGN"),
new MyCurrency("₤", "LIRA SIGN"),
new MyCurrency("₥", "MILL SIGN"),
new MyCurrency("₦", "NAIRA SIGN"),
new MyCurrency("₧", "PESETA SIGN"),
new MyCurrency("₨", "RUPEE SIGN"),
new MyCurrency("₩", "WON SIGN"),
new MyCurrency("₪", "NEW SHEQEL SIGN"),
new MyCurrency("₫", "DONG SIGN"),
new MyCurrency("€", "EURO SIGN"),
new MyCurrency("₭", "KIP SIGN"),
new MyCurrency("₮", "TUGRIK SIGN"),
new MyCurrency("₯", "DRACHMA SIGN"),
new MyCurrency("₰", "GERMAN PENNY SIGN"),
new MyCurrency("₱", "PESO SIGN"),
new MyCurrency("₲", "GUARANI SIGN"),
new MyCurrency("₳", "AUSTRAL SIGN"),
new MyCurrency("₴", "HRYVNIA SIGN"),
new MyCurrency("₵", "CEDI SIGN"),
new MyCurrency("₶", "LIVRE TOURNOIS SIGN"),
new MyCurrency("₷", "SPESMILO SIGN"),
new MyCurrency("₸", "TENGE SIGN"),
new MyCurrency("₹", "INDIAN RUPEE SIGN"),
new MyCurrency("₺", "TURKISH LIRA SIGN")
};

Spinner spinnerCurrency;
TextView textBigCurrency;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

textBigCurrency = (TextView)findViewById(R.id.bigcurrency);
spinnerCurrency = (Spinner)findViewById(R.id.spinnerCurrency);

MySpinnerAdapter adapterCurr =
new MySpinnerAdapter(MainActivity.this,
R.layout.row,
MyCurrencyAll);
spinnerCurrency.setAdapter(adapterCurr);
spinnerCurrency.setOnItemSelectedListener(onItemSelectedListener);

}

OnItemSelectedListener onItemSelectedListener =
new OnItemSelectedListener(){

@Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {
MyCurrency curr = (MyCurrency)(parent.getItemAtPosition(position));
textBigCurrency.setText(String.valueOf(curr.getSymbol()));
}

@Override
public void onNothingSelected(AdapterView<?> parent) {}

};

// define our custom class
public class MyCurrency {

private String symbol;
private String desc;

public MyCurrency(String symbol, String desc) {
this.symbol = symbol;
this.desc = desc;
}


public String getSymbol() {
return this.symbol;
}

public String getDesc() {
return this.desc;
}
}

// custom adapter
public class MySpinnerAdapter extends ArrayAdapter<MyCurrency> {

private MyCurrency[] myCurrencyArray;

public MySpinnerAdapter(Context context, int textViewResourceId,
MyCurrency[] myObjs) {
super(context, textViewResourceId, myObjs);
this.myCurrencyArray = myObjs;
}

public int getCount() {
return myCurrencyArray.length;
}

public MyCurrency getItem(int position) {
return myCurrencyArray[position];
}

public long getItemId(int position) {
return position;
}

@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
return getCustomView(position, convertView, parent);
}

@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return getCustomView(position, convertView, parent);
}

private View getCustomView(int position, View convertView,
ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.row, parent, false);

TextView textSymbol = (TextView) view
.findViewById(R.id.textSymbol);
textSymbol.setText(myCurrencyArray[position].getSymbol());
TextView textDesc = (TextView) view
.findViewById(R.id.textDesc);
textDesc.setText(myCurrencyArray[position].getDesc());

return view;
}
}

}

/res/layout/row.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="wrap_content"
android:orientation="vertical"
android:padding="10dp" >

<TextView
android:id="@+id/textSymbol"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />
<TextView
android:id="@+id/textDesc"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="italic" />
</LinearLayout>

/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.androidspinnertext.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" />

<Spinner
android:id="@+id/spinnerCurrency"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/bigcurrency"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:textSize="150sp" />

</LinearLayout>


download filesDownload the files.

Or, download the APK HERE.

Related:
Display available currencies java.util.Currency

Lançado Android 4.4.3 KitKat!

E finalmente o Android 4.4.3 é lançado!


Infelizmente, nenhuma novidade foi identificada na nova versão do Android. Ao que parece, o KitKat 4.4.3 irá mesmo trazer apenas consertos de bugs e pequenos ajustes, tais como:

correção de queda de conexão frequente; 
correção e otimização do serviço mm-qcamera-daemon;
correção de foco da câmera em modos HDR e normal;
várias correções no Bluetooth;
correção de reinicializações aleatórias;
atalhos de aplicativos removidos após atualização;
correção de segurança do USB debug;
correção de wakelock;
correção de segurança em atalhos de apps;
correção de auto-conexão Wi-Fi;
diversas correções de câmera;
correção de MMS, E-mail, Calendário, Contatos, DSP, IPv6 e VPN;
correção de bloqueio na tela de ativação;
correção de LED em chamadas não atendidas;
correções de legenda;
correção do gráfico de dados utilizados.


Ainda não apareceram as imagens de fábrica para os dispositivos Nexus, mas agora é apenas uma questão de dias (talvez horas) até que o update esteja disponível para os Nexus desbloqueados.

Pro Android UI

Pro Android UI

If you’re an Android application developer, chances are you’re using fixed, scrolling, swipe-able, and other cutting-edge custom UI Designs in your Android development projects. These UI Design approaches as well as other Android ViewGroup UI layout containers are the bread and butter of Pro Android User Interface (UI) design and Android User Experience (UX) design and development.

Using a top down approach, Pro Android UI shows you how to design and develop the best user interface for your app, while taking into account the varying device form factors in the increasingly fragmented Android environment. Pro Android UI aims to be the ultimate reference and customization cookbook for your Android UI Design, and as such will be useful to experienced developers as well as beginners.

With Android’s powerful UI layout classes, you can easily create everything from the simplest of lists to fully tricked-out user interfaces. While using these UI classes for boring, standard user interfaces can be quite simple, customizing a unique UI design can often become extremely challenging.


What you’ll learn

  • How to design and develop a sleek looking and highly functional user interface (UI) design and experience (UX) design using Android APIs
  • What Android layout containers are, and how to best leverage them
  • How to design user-friendly UI layouts that conform to Android UI guidelines
  • What, when, why and how to use fundamental Android UI layout containers (ViewGroup subclasses) and Android UI widgets (View subclasses)
  • How to use new media assets such as images, video, and animation in a UI
  • How to create UI Fragments for UI design for specific ActionBar or Activity classes that you wish to create for UI designs within your applications
  • Scaling UI Design for the various Android smartphone and tablet form factors

  • Who this book is for
    This book is for experienced Android app developers.  It can also be for app developers and UI designers working on other platforms like iOS and BlackBerry who might also be interested in Android.

    Table of Contents

    Part I. Introduction to the Core Classes for Android UI Design: Development Tools, Layout Containers and Widgets
    1. Android UI Design Tools: Setting Up Your Android Development System
    2. Android UI Layouts: Layout Containers and the ViewGroup Class
    3. Android UI Widgets: User Interface Widgets and the View Class

    Part II. Introduction to Android Menu Class for UI Design: OptionsMenu, ContextMenu, PopupMenu and ActionBar
    4. Android UI Options Menus: OptionsMenu Class and an Introduction to the Android ActionBar
    5. Android UI Local Menus: The ContextMenu Class and PopupMenu Class
    6. Android UI Action Bar: Advanced ActionBar Design & ActionBar Class

    Part III. Android UI: Layout Considerations, Concepts & UI Containers: LinearLayout, RelativeLayout, FrameLayout
    7. Android UI Design Considerations: Styles, Screen Density Targets and New Media Formats
    8. Android UI Design Concepts: Wire-framing & UI Layout Design Patterns
    9. Android UI Layout Conventions, Differences and Approaches
    10. Android UI Theme Design & Digital Media Concepts

    Part IV. Basic Android UI Design: Basic Layout Containers: FrameLayout, LinearLayout,
    RelativeLayout, GridLayout
    11. Android’s FrameLayout Class: Using Digital Video in your UI Design
    12. Android’s LinearLayout Class: Horizontal and Vertical UI Design
    13. Android’s RelativeLayout Class: Complex UI Design Via a Single Layout Container
    14. Android’s GridLayout Class: Optimized UI Design using a Grid-based Layout

    Part V. Advanced Android UI Design: Advanced Layout Containers: DrawerLayout, SlidingPane, ViewPager, Strips
    15. Android DrawerLayout Class: Using Left and Right Side UI Drawer Design
    16. Android SlidingPaneLayout Class: Optimized UI Design using a Grid-based Layout Container
    17. Android ViewPager Class: Using View Paging to Navigate Complex View Hierarchies
    18. Android PagerTabStrip and PagerTitleStrip Classes: Design Navigation UI Elements for the ViewPager Layout

    الأحد، 13 أبريل 2014

    Custom Spinner with different normal view and drop-down view

    It's another example of custom Spinner, which have different normal view and drop-down view, using custom object and adapter for the spinner. Our custom object have two String, one for display text, another for Internet address.

    In normal view, returned by getView() of our custom ArrayAdapter, there are one TextView to show the display text, and another button to open the target address if clicked. In drop-down view, returned by getDropDownView() of our custom ArrayAdapter, there are two TextView to show the display text, and the target address.


    /res/layout/row.xml, the layout of the normal view.
    <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="wrap_content"
    android:orientation="vertical" >

    <TextView
    android:id="@+id/gotext"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:textStyle="bold"/>
    <Button
    android:id="@+id/gobutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
    </LinearLayout>

    /res/layout/dropdown.xml, the layout of the drop-down view.
    <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="wrap_content"
    android:orientation="vertical"
    android:padding="10dp" >

    <TextView
    android:id="@+id/gotext"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:textStyle="bold" />
    <TextView
    android:id="@+id/goaddr"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textStyle="italic" />
    </LinearLayout>

    /res/layout/activity_main.xml, the layout of our activity.
    <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.androidspinnertext.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" />

    <Spinner
    android:id="@+id/spinnergo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
    <TextView
    android:id="@+id/textgo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

    </LinearLayout>

    MainActivity.java
    package com.example.androidspinnertext;

    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemSelectedListener;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.Spinner;
    import android.widget.TextView;

    public class MainActivity extends Activity {

    MyClass[] objGo ={
    new MyClass("Android-er", "http://android-er.blogspot.com/"),
    new MyClass("Arduino-er", "http://arduino-er.blogspot.com/"),
    new MyClass("Hello Raspberry Pi", "http://helloraspberrypi.blogspot.com/"),
    new MyClass("MyPhotoBlog", "http://photo-er.blogspot.com/"),
    new MyClass("g+ Androider+", "https://plus.google.com/102969667192015169220"),
    new MyClass("Youtube playlist: Android Development", "http://www.youtube.com/playlist?list=PLP7qPet500deChwUlhq-GsDl8Tun4_WMD"),
    new MyClass("Google Play", "https://play.google.com/store")
    };

    Spinner spinnerGo;
    TextView textViewGo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textViewGo = (TextView)findViewById(R.id.textgo);
    spinnerGo = (Spinner)findViewById(R.id.spinnergo);
    MySpinnerAdapter adapterGo =
    new MySpinnerAdapter(MainActivity.this,
    R.layout.row,
    objGo);
    spinnerGo.setAdapter(adapterGo);
    //spinnerGo.setOnItemSelectedListener(onItemSelectedListenerGo);

    }

    OnItemSelectedListener onItemSelectedListenerGo =
    new OnItemSelectedListener(){

    @Override
    public void onItemSelected(AdapterView<?> parent, View view,
    int position, long id) {
    MyClass obj = (MyClass)(parent.getItemAtPosition(position));
    textViewGo.setText(String.valueOf(obj.getTarget()));
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {}

    };

    //define our custom class
    public class MyClass{

    private String text;
    private String target;

    public MyClass(String text, String target){
    this.text = text;
    this.target = target;
    }

    public void setText(String text){
    this.text = text;
    }

    public String getText(){
    return this.text;
    }

    public void setValue(String target){
    this.target = target;
    }

    public String getTarget(){
    return this.target;
    }
    }

    //custom adapter
    public class MySpinnerAdapter extends ArrayAdapter<MyClass>{

    private MyClass[] myObjs;

    public MySpinnerAdapter(Context context, int textViewResourceId,
    MyClass[] myObjs) {
    super(context, textViewResourceId, myObjs);
    this.myObjs = myObjs;
    }

    public int getCount(){
    return myObjs.length;
    }

    public MyClass getItem(int position){
    return myObjs[position];
    }

    public long getItemId(int position){
    return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = getLayoutInflater();
    View spView = inflater.inflate(R.layout.row, parent, false);

    TextView sp_GoText = (TextView)spView.findViewById(R.id.gotext);
    sp_GoText.setText(myObjs[position].getText());

    Button sp_GoButton = (Button)spView.findViewById(R.id.gobutton);
    sp_GoButton.setText(myObjs[position].getTarget());

    sp_GoButton.setOnClickListener(new OnClickListener(){

    @Override
    public void onClick(View v) {
    Uri uri = Uri.parse(myObjs[position].getTarget());
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    startActivity(intent);
    }});

    return spView;
    }

    @Override
    public View getDropDownView(int position, View convertView,
    ViewGroup parent) {
    LayoutInflater inflater = getLayoutInflater();
    View dropDownView = inflater.inflate(R.layout.dropdown, parent, false);

    TextView dd_GoText = (TextView)dropDownView.findViewById(R.id.gotext);
    dd_GoText.setText(myObjs[position].getText());

    TextView dd_GoAddr = (TextView)dropDownView.findViewById(R.id.goaddr);
    dd_GoAddr.setText(myObjs[position].getTarget());

    return dropDownView;

    }

    }

    }



    download filesDownload the files.

    Rumor: Ícones de Aplicativos da Google pode ganhar cara nova!

    Será que não passa de Rumores? Adorei os novos estilos de ícones :3


    Antes de mais nada, o texto foi traduzido pelo belíssimo Google Tradutor!

    Incluído em diretrizes de design do Android é uma seção sobre a iconografia. As diretrizes dão muito instruções específicas sobre como projetar um ícone lançador para Android - ele deve ter uma silhueta única, ele deve ter uma ligeira perspectiva de queda, e deve ser claramente visível, não importa o papel de parede está por trás disso.

    Muitos já opinou, no entanto, que é estranho que o Google mantém iconografia diferente para seus aplicativos no Android e os seus serviços web correspondentes. Por exemplo, na web, o ícone do Gmail é um envelope fechado plana, com uma longa sombra, enquanto o Android é um envelope aberto mais dimensional com o M que aparece no "papel" dentro.

    Pode-se argumentar que ter ícones diferentes para diferentes plataformas faz sentido, mas se os rumores de hoje é para ser acreditado, ícones do Android pode em breve dar um passo em direção ao estilo dos seus homólogos da web.

    Nível de confiança

    Este boato ganha um 7/10. Os pontos são deduzidos porque as mudanças puramente baseada em design podem variar um pouco que antecederam a liberação final, e porque não temos qualquer evidência baseada em software para estas mudanças (como ícones escondidos em uma desmontagem APK por exemplo). Dito isto, a partir da informação disponível para nós, parece provável que este rumor virá à fruição de alguma forma, mesmo se o que estamos vendo não é o produto final.

    O Rumor

    O rumor, se você ainda não adivinhou-lo já, é que o Google vai mudar o estilo de seus ícones do lançador para aplicativos Android para mais se assemelham aos de suas propriedades na web. Este novo estilo, conhecido internamente como "Moonshine" veria ícones Android assumir uma aparência um pouco mais plana, com longas sombras duras por trás elementos de destaque, que lembram o que pode ser visto nas diretrizes de ativos visuais existentes do Google (vê-los no Behance ).

    A implicação aqui, além de muito novos ícones, seria a de que as diretrizes de design do Android que precisam ser atualizados. De repente, ícones quadrados ou circulares clichê ficaria um pouco fora do lugar, e aqueles com texturas ou outros elementos tridimensionais teria de cair em consonância com este novo estilo para se manter atualizado.

    O que é interessante, porém, é que os ícones que vemos (abaixo) que não têm correspondentes ícones da web não são idênticos aos ícones da web existentes - esses ícones olhar diferente e mais sofisticado. É difícil explicar esta discrepância, a menos que o Google planeja atualizar a iconografia de seus produtos web com a nova estética também. Em um mundo ideal, as coisas ou ser iguais ou diferentes, não apenas muito semelhantes , mas, se os ícones do Android e na web foram ambos atualizados, seria uma mudança bem-vinda uma vez que - como veremos - não todos do Google Os ícones do Web ainda carregam a mesma estética.

    A Evidência

    Graças a uma fonte familiarizada com os novos modelos, podemos ver abaixo os ícones para ouvir música, livros, filmes, e jogos, ao lado do Google+, Calendar, Pessoas, Chrome, YouTube, Maps, Gmail, Hangouts, Câmera, eo Play Store. Curiosamente, o ícone Play Store visto aqui tem um símbolo Jogar com um esquema de cor verde azulada ao invés do esquema multicolorido atualmente incorporado em branding Play Store. Além disso, enquanto a música, livros e jogos, aparentemente, mantiveram suas cores da marca atual, filmes tem um ícone roxo. Mais uma vez, porém, não há nenhuma maneira real para ter a certeza de que no processo de concepção desses ícones são, por isso tudo é possivelmente sujeitos a alterações.


    Para visualizar mais facilmente a mudança, vamos olhar para os ícones acima que correspondente ícones da web em relação ao seu web atual e colegas Android. Mais uma vez, note que, embora, de acordo com a do Google diretrizes visuais , os ícones da web devem, teoricamente, todos parecem relativamente plana, com sombras duras, os ícones da web atual não pode realmente ser chamado consistente na sua abordagem. Da mesma forma, os ícones atuais do Android não combinam perfeitamente com todas as sugestões definidas adiante em diretrizes do Android


    Considerações Finais


    Se o rumor panelas para fora, ícones Android do Google está indo para obter uma reforma. Se estes são formas finais dos ícones é impossível dizer no momento, mas seria interessante ver um take hold estética mais plana, mais de acordo com a natureza simplificada, destilado de ícones atuais da web do Google. Também será interessante ver o que muda isso traz para as orientações existentes . Aqui está esperando que - sempre que ocorrer a mudança - vamos obter algum tipo de consistência.