Featured Posts

Localization-Dang Thanh Binh

Author: Dang Thanh Binh

I – Introduction:

Localization is very important in order to make Android app reach most of the users. This how-to will demonstrate simple technique of using resources to support localization.

II – Advantages and disadvantages:

Advantage of this method is ease of use and implement. We can have as many languages as we want as long as we create enough resources to support our languages.

However, the more complicated the app is as well the more languages we need to support is the more we need to do on the resources part.

III – Implementation:

First create many localized folders as many languages we want to support, which is how many languages we want to display our text. In the example, there are 3 languages: English (default), Italian and French.

 

Now we create a resource file for each localized folder, where we will insert the text as a string resource. Created our texts, we are going to implement graphically our selection language Activity:

 

<linearlayout android:layout_height=”fill_parent” android:layout_width=”fill_parent” android:orientation=”vertical” xmlns:android=”http://schemas.android.com/apk/res/android“>

 

<spinner android:id=”@+id/spinner1″ android:layout_height=”wrap_content” android:layout_width=”match_parent”>

 

<button android:id=”@+id/button1″ android:layout_height=”wrap_content” android:layout_width=”match_parent” android:onclick=”onClick” android:text=”Start activity”>

 

 

</button></spinner></linearlayout>

The Activity has consisted of only one spinner, which allows the choice of language, and a button to start the Activity containing our text:

 

public class LocalizationUpdaterActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Spinner spinner = (Spinner) findViewById(R.id.spinner1);

spinner.setPrompt("select language");

ArrayAdapter<string> adapter = new ArrayAdapter<string>(this,

android.R.layout.simple_spinner_item, languages);

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

spinner.setAdapter(adapter);

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

public void onItemSelected(AdapterView arg0, View arg1,

int arg2, long arg3) {

Configuration config = new Configuration();

switch (arg2) {

case 0:

config.locale = Locale.ENGLISH;

break;

case 1:

config.locale = Locale.ITALIAN;

break;

case 2:

config.locale = Locale.FRENCH;

break;

default:

config.locale = Locale.ENGLISH;

break;

}

getResources().updateConfiguration(config, null);

}

public void onNothingSelected(AdapterView arg0) {

// TODO Auto-generated method stub

}

});

}

public void onClick(View v){

startActivity(new Intent(getBaseContext(), TextActivity.class));

}

private String[] languages = { "Inglese", "Italiano", "Francese" };

}

The layout of the Activity that shows the text contains only a TextView that refers to our resource of type String, then by the choice of language made we can see the different texts.

 

 

Standard
Featured Posts

How to Use the Media Player in Android

How to Use the Media Player in Android

Introduction
This introduction is about how to use the Media Player in Android.
When should you apply this? (Optional)
This app is applied when you want to listen to music. There are two modes which are online mode and the offline mode in this app. When there is no Internet connection, user can listen to music locally. If the network connection is available, user can listen to music online on nhaccuatui.com or nhacvui.com website.
Advantages & disadvantages
Advantage:
It’s easy to use.
When users use the online mode, users can listen to the latest songs.
When users use the offline mode, users can listen to their songs from the sdcard.
Disadvantage:
If the path for sdcard is incorrect, the method will not run correctly.
If the sdcard is not push into the emulator, the emulator cannot read the file from the sdcard.

Requirements
The Android emulator needs to add the sdcard first.
Users need to push the music into the sdcard.
If user’s network needs authentication to access the Internet, then user needs to configure the proxy setting.
The minimum requirements for Media Player must have songs, play/pause button, previous button, next button, shuffle song, repeat song button, playlist button and a seek bar.

Steps & Screen shots
First, declare all the buttons and seek bar that mentioned above:

private SeekBar seekBar;
private Button buttonPlayPause, buttonUpdate, buttonNext, buttonPrev;
private CheckBox check_shuffle, check_repeat;

Second, down cast and add listener for each button:

buttonPlayPause = (Button) findViewById(R.id.btn_play_pause);
buttonUpdate = (Button) findViewById(R.id.btn_update); buttonNext = (Button) findViewById(R.id.btn_next);
buttonPrev = (Button) findViewById(R.id.btn_prev);
seekBar = (SeekBar) findViewById(R.id.seekBar1);
check_shuffle = (CheckBox) findViewById(R.id.check_shuffle);
check_repeat = (CheckBox) findViewById(R.id.check_repeat);

Adding listener:

buttonPlayPause.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
buttonClick();
updateSongList();
}
});

buttonNext.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
nextSong();
setCount(getCount() + 1);
updateSongList();
}
});

buttonUpdate.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// highlightListElement(currentPosition);
updateSongList();
}
});

buttonPrev.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
prevSong();
setCount(getCount() + 1);
updateSongList();
}
});

seekBar.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
seekChange(v);
return false;
}
});

To change the seek bar, user needs to add this method:

private void seekChange(View v) {
if (mp.isPlaying()) {
SeekBar sb = (SeekBar) v;
mp.seekTo(sb.getProgress());
}
}

To update the song list, user needs to implement this method:

public void updateSongList() {

File home = new File(MEDIA_PATH);
if (getState() == PLAY_LIST) {

songs.clear();
// check file type
if (home.listFiles(new Mp3Filter()).length > 0) {
for (File file : home.listFiles(new Mp3Filter())) {
songs.add(file.getName());
addSong(file.getName());
}
temp_songs.clear();
for (int i = 0; i < songs.size(); i++) {
temp_songs.add(i);
}

// sort in alphabetical order
Collections.sort(songs, new Comparator() {
@Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
});
songList = new ArrayAdapter(this, R.layout.song_item,
songs);
songList.notifyDataSetChanged();
setListAdapter(songList);

}
} else if (getState() == NOW_PLAYING) {

ArrayAdapter nowPlaying_list = new ArrayAdapter(
this, R.layout.song_item, nowPlaying);
nowPlaying_list.notifyDataSetChanged();
setListAdapter(nowPlaying_list);

} else if (getState() == RECENTLY_ADDED) {

recentlyAdded.clear();
for (File file : home.listFiles(new Mp3Filter())) {
recentlyAdded.add(file.getName());
}
temp_songs.clear();
for (int i = 0; i < songs.size(); i++) {
temp_songs.add(i);
}

ArrayAdapter recentlyAdded_list = new ArrayAdapter(
this, R.layout.song_item, recentlyAdded);
recentlyAdded_list.notifyDataSetChanged();
setListAdapter(recentlyAdded_list);

}

}

Next is the code for the next and previous buttons:

private void nextSong() {

if (check_shuffle.isChecked()) {

if (check_repeat.isChecked()) {

if (temp_songs.size() == swap_temp_songs.size()) {

swap_temp_songs.clear();

int pos = rand.nextInt(temp_songs.size());

if (swap_temp_songs.isEmpty()) {
pos = rand.nextInt(temp_songs.size());
swap_temp_songs.add(pos);
} else {
while (checkExist(swap_temp_songs, pos)) {
pos = rand.nextInt(temp_songs.size());
}
swap_temp_songs.add(pos);
}

setCurrentPosition(pos);
if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
playSong(MEDIA_PATH + songs.get(pos));
} else if (getState() == RECENTLY_ADDED) {
playSong(MEDIA_PATH + recentlyAdded.get(pos));
}

} else {

int pos = rand.nextInt(temp_songs.size());

if (swap_temp_songs.isEmpty()) {
pos = rand.nextInt(temp_songs.size());
swap_temp_songs.add(pos);
} else {
while (checkExist(swap_temp_songs, pos)) {
pos = rand.nextInt(temp_songs.size());
}
swap_temp_songs.add(pos);
}
setCurrentPosition(pos);
if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
playSong(MEDIA_PATH + songs.get(pos));
} else if (getState() == RECENTLY_ADDED) {
playSong(MEDIA_PATH + recentlyAdded.get(pos));
}

}

} else {

if (temp_songs.size() == swap_temp_songs.size()) {

Toast.makeText(getBaseContext(), “End of Playlist”,
Toast.LENGTH_LONG).show();

} else {

int pos = rand.nextInt(temp_songs.size());

if (swap_temp_songs.isEmpty()) {
pos = rand.nextInt(temp_songs.size());

swap_temp_songs.add(pos);
} else {
while (checkExist(swap_temp_songs, pos)) {
pos = rand.nextInt(temp_songs.size());
}
swap_temp_songs.add(pos);
}
setCurrentPosition(pos);
if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
playSong(MEDIA_PATH + songs.get(pos));
} else if (getState() == RECENTLY_ADDED) {
playSong(MEDIA_PATH + recentlyAdded.get(pos));
}

}
}

} else {

if (getCurrentPosition() == (songs.size() – 1)) {

if (check_repeat.isChecked()) {

setCurrentPosition(0);
if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
playSong(MEDIA_PATH + songs.get(getCurrentPosition()));
} else if (getState() == RECENTLY_ADDED) {
playSong(MEDIA_PATH
+ recentlyAdded.get(getCurrentPosition()));
}

} else {

Toast.makeText(getBaseContext(), “End of Playlist”,
Toast.LENGTH_LONG).show();

}
} else {

setCurrentPosition(getCurrentPosition() + 1);
if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
playSong(MEDIA_PATH + songs.get(getCurrentPosition()));
} else if (getState() == RECENTLY_ADDED) {
playSong(MEDIA_PATH
+ recentlyAdded.get(getCurrentPosition()));
}

}
}

if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
nowPlaying.clear();
nowPlaying.add(songs.get(getCurrentPosition()));
} else if (getState() == RECENTLY_ADDED) {
nowPlaying.clear();
nowPlaying.add(recentlyAdded.get(getCurrentPosition()));
}

}

// back to previous song
private void prevSong() {
if (getCurrentPosition() == 0) {

if (check_repeat.isChecked()) {

if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
setCurrentPosition(songs.size() – 1);
playSong(MEDIA_PATH + songs.get(getCurrentPosition()));
} else if (getState() == RECENTLY_ADDED) {
setCurrentPosition(recentlyAdded.size() – 1);
playSong(MEDIA_PATH
+ recentlyAdded.get(getCurrentPosition()));
}

} else {

Toast.makeText(getBaseContext(), “Top of Playlist”,
Toast.LENGTH_LONG).show();

}
} else {
setCurrentPosition(getCurrentPosition() – 1);
}

if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
nowPlaying.clear();
nowPlaying.add(songs.get(getCurrentPosition()));
} else if (getState() == RECENTLY_ADDED) {
nowPlaying.clear();
nowPlaying.add(recentlyAdded.get(getCurrentPosition()));
}

}

The play/pause button:
private void buttonClick() {

if (buttonPlayPause.getText() == getString(R.string.play_str)) {
buttonPlayPause.setText(getString(R.string.pause_str));
try {
if (getCount() == 0) {
if (getState() == PLAY_LIST || getState() == NOW_PLAYING) {
nowPlaying.clear();
nowPlaying.add(songs.get(getCurrentPosition()));
} else if (getState() == RECENTLY_ADDED) {
nowPlaying.clear();
nowPlaying.add(recentlyAdded.get(getCurrentPosition()));
}
playSong(MEDIA_PATH + songs.get(getCurrentPosition()));
}
mp.start();
startPlayProgressUpdater();

} catch (IllegalStateException e) {
mp.pause();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
} else {
buttonPlayPause.setText(getString(R.string.play_str));
mp.pause();
}

}

Override the onBackPressed method in order to stop the music when user clicks the back button.

@Override
public void onBackPressed() {
mp.stop();
mp.release();
super.onBackPressed();

}

Standard
Featured Posts

Search list view

Introduction

You have a long list, you do not want to skim through the entire list to find the item you want, solution? Include an EditText search box at the top of the screen, we will filter the list using the input text and display result.

Requirements

import android.text.Editable;

import android.text.TextWatcher;

 

There are two types of configuration for this search approach:

–          Override toString() of the list item object

–          Program your own search method in the onTextChanged()

Advantage and disadvantage

Advantages:

–          Don’t need any database

–          Default APIs

Disadvantages:

–          Can only query using text (string data type) by default

Steps and code snapshot

Basically, the text watcher will use a filter object of the current activity to redisplay the screen. This filter object will search using the toString() of the list item object. Thus, overriding the toString() to return the desired String for query is the recommended way.

For example, we have a list of companies with the following attributes: name, tax number, address. You want to search the list using company name, then override Company.toString() to return Company.name.

If you want to customize the search filter to do fancier things (not recommended), you will have to either find a way to make your own version of Filter object for the current activity or handle everything from GUI to functions in the onTextChanged() without the help of built-in API (again, not recommended).

 

public void onCreate(Bundle b) {

super.onCreate(b);

 

// initialize search box and list, our search box is at the top

EditText inputSearch = (EditText) findViewById(R.id.eventList_inputSearch);

ListView list = (ListView) findViewById(R.id.eventList_list);

 

// replace generic type (Object in this example) with your object of choice

// this array list holds the list item data that will be displayed

ArrayList<Object> array = new ArrayList<Object>();

ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(this, array);

list.setAdapter(adapter);

 

inputSearch.addTextChangedListener(new TextWatcher() {

 

// need to override this function

@Override

public void onTextChanged(CharSequence cs, int arg1, int arg2,

int arg3) {

// if you override toString() of the list item object,

// include this line

//

// CurrentActivity is the class name of the activity holding the

// list view

CurrentActivity.this.adapter.getFilter().filter(cs);

// else write your own search engine and visual effect

// handling here

}

 

@Override

public void beforeTextChanged(CharSequence arg0, int arg1,

int arg2, int arg3) {

// handle fancy visual effect or other function if you want

}

 

@Override

public void afterTextChanged(Editable arg0) {

// handle fancy visual effect or other function if you want

}

 

});

}

 

Standard
Featured Posts

Multipart entity Upload

Introduction

Uploading large file is risky: your application might crash during uploading or throw StackOverflowException. We provide a solution: use Multipart Entity by Apache to upload these large files and a php script will handle the storage of the file.

However, there is a catch. This is not provided by default in API 8 (SDK 2.2) in your Android library while most of us would be programming our apps on this API.

 

Requirements

Download the following jar files, we provide the links for your convenience:

HttpMime 4.1:

http://repo1.maven.org/maven2/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar

HttpCore 4.2.1:

http://apache.mirrors.tds.net//httpcomponents/httpcore/binary/httpcomponents-core-4.2.1-bin.tar.gz

HttpClien t4.2.1

http://apache.mirrors.tds.net//httpcomponents/httpclient/binary/httpcomponents-client-4.2.1-bin.tar.gz

Then, add them to your library:

–          Create a new folder ‘libs’ in your Android project.

–          Right-click ‘libs’ and choose Import -> General -> File System, then Next, Browse in the file system to find the library’s parent directory (where you downloaded it to).

–          Click OK and then click the directory name (not the checkbox) in the left pane, then check the relevant JAR in the right pane. This puts the library into your project.

–          Right-click on your project, choose Build Path -> Configure Build Path, then click the Libraries tab, then Add JARs…, navigate to your new JAR in the ‘libs’ directory and add it.

 

 

Advantage and disadvantage

Advantages:

–          Uploading large file easily in API 8

–          No need to worry about resource lockup during uploading

Disadvantages:

–          Require outside libraries

Steps and code snapshot

The magical function:

 

public void upload() {

BasicResponseHandler response = new BasicResponseHandler();

HttpClient client = new DefaultHttpClient();

// put link to your php script that handles uploading

HttpPost post = new HttpPost(http://www.YourURL/upload.php&#8221;);

// link to your file

File file = new File(YourFilePath);

FileBody fBody = new FileBody(file);

MultipartEntity reqEntity =

new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

 

//the variable ‘file’ here must be the same in server php script

reqEntity.addPart(“file”, fBody);

httpPost.setEntity(reqEntity);

 

//receive response from server here

String result = client.execute(httpPost, response);

Log.i(“File upload”, result);

}

 

Server’s php script: upload.php (reference in the URL in HttpPost in the above function

 

<?php

// variable ‘file’ must have the same name with the one

// in java function

// basic upload procedure in php and return result

$filename = $_FILES[‘file’][‘name’];

$tmpname=$_FILES[‘file’][‘tmp_name’];

if(move_uploaded_file($tmpname, “upload/$filename“)) {

echo “The file ” . basename( $_FILES[‘file’][‘name’]) .

” has been uploaded”;

} else {

echo “There was an error uploading the file ” . basename( $_FILES[‘file’][‘name’]). “, please try again!”;

}

?>

Standard
Featured Posts

How-to get and use JSON from a website API

Mobile Application Development

How-to get and use JSON from a website API

Student: Hoang Huy Cat          ID: s3275199

Student: Dang Quang Binh      ID: s3274973

Lecturer: George Nguyen

 

  1. Introduction and reason

When developers make Android project, sometime they need to fetch information from a website to their application. This will require a webpage API and some knowledge of how to get information from what that website provides us, in this case let’s say JSON.

  1. Advantages

–          JSON stands for JavaScript Object Notation, it is a lightweight text-data interchange format, “self-describing” and easy to understand.

–          With JSON developers can get information that provided by a website very easily.

  1. Disadvantages

–            JSON has dynamic format lead to a problem that it’s hard to reuse.

 

  1. Requirements

–          API key from the website to connect and retrieve JSON file.

–          Know how to read JSON format.

 

  1. Step & Screen Shot

–          First, you have to get the key from provided website. Usually you have to sign up as developer and  the website will send you an email with the API key.

Now go to the website API-document

–          For example I want to fetch Movie information for my application, I go to Movie Info in the Docs Navigation. I’ll get this page

–          The page gives us the URL to get the JSON with api-key. All we have to do is using HttpGet to fetch JSON file and use String builder to get all information in the JSON as a string. The HttpGet takes above URL as parameter.

–          Now take a look at the JSON to know how to get information from it


–          The “{ }” provides us a JSONObject, “[ ]” provides us a JSONArray.

–           From the picture above we can see the open “{” for the JSONObject named “movie”, inside this object we have strings and JSON array.

–          Like I said earlier, after we get JSON from the website, we now have it as a string name “movieInfo” with the method above. Now we have to cast it into a JSONObject using

JSONObject movieObject = new JSONObject(movieInfo);

–          After having the big object we can get specific information from it. For example

+ movieObject.getString(“id”) will give us the ID of this movie which is 770672122.

+ movieObject.getString(“title”) gives us “Toy Story 3”.

+ “genres” is a JSONArray so we will use moviObject.getJSONArray(“genres”) this will give us an array of String [“Animation”, ”Kid & Family”, “Science Fiction & Fantasy”, “Comedy”] so we can use however we want.

 

–          That’s all the steps needed to use an API from a website that provide JSON to exchange information.

Standard
Featured Posts

Play music using MusicPlayer class in Android SDK

Author: Ngoc Khanh Tran – s3312498

I – Introduction:

Music is one of the most important aspects of live. In real live, it helps people relax, release their stress and merge themselves into the songs. In Android environment, music can event do better: It can be used as decoy for game applications, used as SFX when pressing buttons or event used as background theme for the applications. Therefore, this tutorial will talk about how to implements music in an Android Application.

II – Advantages and disadvantages:

Adding music will eat the memory of the device. If the application has both background and SFX music, the eaten memory will be big.

However, adding music brings the real feeling for the application and separates it from the static application. In some type of application, playing music is vital (Music player application, Alarm application…).

III – Requirement:

In Android SDK, there is a class name MediaPlayer in android.media.MediaPlayer that can be used to play music. It supports many types of music, including MP3, WAV, FLAC, AAC and MIDI.  For the other types, there are many proper libraries on the Internet.

This tutorial will demonstrate how to use the MediaPlayer class in a simple Music Player application. From this part the readers are assumed to have basic knowledge about Android GUI programming.

IV – Implement:

The first step is to create the GUI for the application. Since this is a simple Music player, there will be only two buttons in it: One is Play button (id btnPlay) and the other is Stop button (id btnStop). The GUI is simply present as below:

To play the music, first we need to initialize the MediaPlayer object inside the Activity:

       MediaPlayer mp = MediaPlayer.create(this.getApplicationContext(), R.raw.music_name);
       //This command create new MediaPlayer for music control
       //R.raw.music_name: The name of the song

After initialize, check if button Play or Stop is press and act as pre-defined:

public void onClick(View view) {

//check which button is pressed
switch (view.getId()) {

//Play button is pressed
       case R.id.btnPlay:
              if (mp.isPlaying())  {
                     mp.start();                    //play music
              } else {
                     mp.pause();                    //pause music
              }
              break;

//Stop button is pressed
       case R.id.btnStop:
              mp.stop();                         //stop music
              break;
       }
}

It is not hard to implement this code. One last thing to remember is to release all the Media Connection by using

       mp.release();

when you have  done with the music play. This will prevent Android application from being memory leaks.

Standard
Featured Posts

Create a Simple Chat Application using Parse BaaS

This tutorial is going to demonstrate step by step how to create a simple chat application on Android 2.2 and above, with instant messaging, online user detection and new message notification using Parse.com Backend as a service.

I.> Create a new project

Open Eclipse (with Android SDK environment set up) and create a new Android Project.

For persistence,

Application Name: ParseChat

ProjectName: ParseChat

Package Name: example.chat

Create a new blank activity. Let’s say LoginActivity.

Some versions of Eclipse would automatically generate the corresponding layouts for the main view and the menu. If not, you’ll have to create new xml files in the corresponding folders in /res

II.> Designing GUI View:

There are 3 views needing to be mentioned: Login, Register, FriendList, and the Chat View. Let’s call the respective Activities for them LoginActivity (already created), RegisterActivity, FriendListActivity and ChatActivity.

Layout for login activity:

—————-

<?xml version=”1.0″ encoding=”utf-8″?>
<ScrollView xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:fillViewport=”true” >

<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical”
android:padding=”10dip” >

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/username”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_email_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”20dip”
android:layout_marginTop=”5dip”
android:hint=”@string/username”
android:singleLine=”true” />

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/password”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_password_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dip”
android:hint=”@string/password”
android:inputType=”textPassword”
android:singleLine=”true” />

<Button
android:id=”@+id/btnLogin”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”10dip”
android:text=”@string/login” />

<TextView
android:id=”@+id/link_to_register”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”40dip”
android:layout_marginTop=”10dip”
android:gravity=”center”
android:text=”@string/register”
android:textSize=”18dip” />
</LinearLayout>

</ScrollView>

—————-

Layout for register activity

—————-

 

<?xml version=”1.0″ encoding=”utf-8″?>
<ScrollView xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:fillViewport=”true” >

<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical”
android:padding=”10dip” >

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/username”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_email_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”20dip”
android:layout_marginTop=”5dip”
android:hint=”@string/username”
android:inputType=”textEmailAddress”
android:singleLine=”true” />

<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/password”
android:textColor=”#372c24″ />

<EditText
android:id=”@+id/login_password_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”5dip”
android:hint=”@string/password”
android:inputType=”textPassword”
android:singleLine=”true” />

<Button
android:id=”@+id/btnLogin”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”10dip”
android:text=”@string/login” />

<TextView
android:id=”@+id/link_to_register”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_marginBottom=”40dip”
android:layout_marginTop=”10dip”
android:gravity=”center”
android:text=”@string/register”
android:textSize=”18dip” />
</LinearLayout>

</ScrollView>

—————-

Layout for Friend List

—————-

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
xmlns:tools=”http://schemas.android.com/tools&#8221;
android:layout_width=”match_parent”
android:layout_height=”match_parent” >

<ListView
android:id=”@+id/friendlist”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical” />

</RelativeLayout>

—————-

Layout for Chat

—————-

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:orientation=”vertical” >

<ScrollView
android:layout_width=”fill_parent”
android:layout_height=”0dip”
android:layout_weight=”1″ >

<TextView
android:id=”@+id/chat_output_txt”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:paddingLeft=”5dp”
android:paddingRight=”5dp”
android:paddingTop=”5dp” />
</ScrollView>

<LinearLayout
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:baselineAligned=”true”
android:orientation=”horizontal”
android:paddingBottom=”5dp”
android:paddingLeft=”5dp”
android:paddingRight=”5dp” >

<EditText
android:id=”@+id/chat_input_txt”
android:layout_width=”0dip”
android:layout_height=”60dip”
android:layout_weight=”1″
android:gravity=”top”
android:inputType=”textMultiLine”
android:scrollHorizontally=”false” >

<requestFocus>
</requestFocus>
</EditText>

<Button
android:id=”@+id/chat_send_btn”
android:layout_width=”80dp”
android:layout_height=”45dp”
android:text=”@string/send” >
</Button>
</LinearLayout>

</LinearLayout>

—————-

III.> Permission for Parse

Parse will need some specific permissions in order to run. Add the following lines into your manifest files, right before the <application> tag.

<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED” />
<uses-permission android:name=”android.permission.VIBRATE” />
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />

IV.> Adding a model into your Android application

1> Model Interface

The model Interface contains all the methods and functions which will be called by the activities.

—————-

public interface Model {
LinkedList<ParseUser> getUsers();
HashMap<String, String> getChatMessages();
String getChannel();
boolean isAuthenticated();
void logout();
void updateUserList();
void sendChatMessage(String userKey, String message);
void login(String username, String password) throws Exception;
void register(String username, String password, String confirm) throws Exception;
void updateUserTracking();
}

—————-

2.> Implementing the model interface

We are going to write a subclass of the Application class to persist data. This class will be implementing the Model interface.

Declaring some static variables and constants:

public class ChatApplication extends Application implements Model {
private static final String APP_ID = “LO6YE92er8izDGLEvBzHUFbO1VrD7a1tRFBp85Ih”;
private static final String CLIENT_KEY = “U1w2aGIoNbkwdGrw5jniGWB9ADBUejO3qtz4dR4l”;
private static LinkedList<ParseUser> users;
private static HashMap<String, String> chatMessages;
private static String channel = “”;
private static ParseUser user = null;
private static PendingIntent pIntent;
private static AlarmManager alarm;
}

Override onCreate()

@Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, ChatApplication.APP_ID, ChatApplication.CLIENT_KEY);
ParseACL acl = new ParseACL();
acl.setPublicReadAccess(true);
ParseACL.setDefaultACL(acl, true);
users = new LinkedList<ParseUser>();
chatMessages = new HashMap<String, String>();
Intent sIntent = new Intent(this, UpdateService.class);
pIntent = PendingIntent.getService(this, 0, sIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
logout();
startTracking();
}

 Implement some simple functions

public LinkedList<ParseUser> getUsers() {
return users;
}

public HashMap<String, String> getChatMessages() {
return chatMessages;
}

public String getChannel() {
return channel;
}

public boolean isAuthenticated() {
return (user != null && user.isAuthenticated());
}

Authentication with Parse

public void login(String username, String password) throws Exception {
username = username.trim().toLowerCase();
validateCredentialsFormat(username, password);
ParseUser.logIn(username, password);
startTracking();
}

public void logout() {
if (user != null) {
ParseUser.logOut();
}
stopTracking();
}

Register a new user with Parse

public void register(String username, String password, String confirm) throws Exception {
username = username.trim().toLowerCase();
validateCredentialsFormat(username, password);
if (!password.equals(confirm)) {
throw new Exception(“Confirmation does not match”);
}
// Registration
ParseUser newUser = new ParseUser();
newUser.setUsername(username);
newUser.setPassword(password);
newUser.signUp();
startTracking();
}

Update the user list

public void updateUserList() {
ParseQuery query = ParseUser.getQuery();
// Only users with the last activities within 5 minutes
Date queryDate = new Date((new Date()).getTime() – 300000);
query.whereGreaterThan(“lastUpdate”, queryDate);
try {
List<ParseObject> list = query.find();
users.clear();
for (ParseObject o : list) {
users.add((ParseUser) o);
}
} catch (ParseException e) {
}
}

Send chat messages using Push Notification

public void sendChatMessage(String target, String message) {
try {
ParsePush push = new ParsePush();
push.setChannel(target);
push.setExpirationTimeInterval(86400);
push.setData(new JSONObject(“{” +
“”action”:”example.chat.MESSAGE”,” +
“”from”:”” + channel + “”,” +
“”to”:”” + target + “”,” +
“”message”:”” + message + “”}”));
push.sendInBackground();
} catch (JSONException e) {
}
}

Some private functions

private void validateCredentialsFormat(String username, String password) throws Exception {
// Some validations
if (username.length() * password.length() == 0) {
throw new Exception(“All fields must be filled”);
}
// The username should not be so complicated
if (!username.matches(“^([A-Za-z]+[A-Za-z0-9_]*)$”)) {
throw new Exception(“Username must start with a letter, and should only contain alphanumeric characters and underscores”);
}
}

private void startTracking() {
stopTracking();
ParseUser usr = ParseUser.getCurrentUser();
if (usr != null && usr.isAuthenticated()) {
channel = usr.getUsername();
user = usr;
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pIntent);
}
}

private void stopTracking() {
channel = “”;
user = null;
alarm.cancel(pIntent);
}

public void updateUserTracking() {
if (user != null && user.isAuthenticated()) {
user.put(“lastUpdate”, new Date());
user.saveEventually();
}
}

3.> Auto update user’s states and auto refreshing

We have to update the current user’s information and retrieve the new information constantly (which I suggest every 4 minutes) so other users can retrieve the latest states of their friends. This is going to be achieved by calling updateUserTracking() function from the model using a service. An AlarmManager will be used for the timing. The timing is triggered in startTracking() and stopped in stopTracking()

public class UpdateService extends Service {

private Model model;

public UpdateService() {
model = (ChatApplication) getApplication();
}

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
model.updateUserList();
model.updateUserTracking();
}

@Override
public IBinder onBind(Intent intent) {
return null;
}
}

V.> The activities

The activities in Android are like the controllers in MVC. The activities receives the inputs from the XML layout, use the implemented model to perform certain tasks corresponding with certain events.

 

 

 

Standard
Android Programming

Working with your MySql database server using PHP, JSON

Author: Hoang Truong Dinh – S3275068
Tang Vinh Thanh – s3245715
Course: COSC2453 – Mobile Application Development
RMIT International University Vietnam
Lecturer: George Nguyen

Introduction

This document will introduce how to working around with your MySql database by you Android application.

When to apply this ?

If you want to store and retrieve data from MySql database server. You will need to implement a PHP API to receive and send data between your Android application and Database Server

For sending data to server we can user HTTP request like POST, for sending from API to your Android application you can use JSON, and use JSON_parse to convert JSONObject to your application’s object.

Advantages and Disadvantages

JSON is very popular nowadays because of its lightweight and easy to implement. However you need to do a little research in order to make it work smoothly

It is a little bit slow to transfer data from server to your application.

Requirements

You need to have database server, an API and your application to do this.

Steps

Here is the steps you need to implement for working with your MySql database

I. Building PHP API

  1. Create DB_Connect.php file
    
    
  2. Create DB_Functions.php file
    
    
  3. Create index.php file
    
    

Copy all of file to your php server, you need remember your php api path

II. Create Class needed in your application

1. Create JSON_Parse.class file

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";
    public JSONParser() {

    }

    public JSONObject getJSONFromUrl(String url, List params) {

        // Making HTTP request
        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new UrlEncodedFormEntity(params));

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();

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

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "n");
            }
            is.close();
            json = sb.toString();
            Log.e("JSON", json);
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        // return JSON String
        return jObj;

    }
}

2. Create Class User_Functions for store function to send and receive JSON

public class UserFunctions {

    private JSONParser jsonParser;
 	//Change URL to your php api path
    private static String URL = "http://mekong.rmit.edu.vn/~s3275068/ah_login_api/";

    public UserFunctions(){
        jsonParser = new JSONParser();
    }

    public JSONObject getUserByUserName(String username){
        // Building Parameters
        List params = new ArrayList();
        // tag must match with the tag in PHP API
        params.add(new BasicNameValuePair("tag", "getuser"));
        params.add(new BasicNameValuePair("username", username));

		JSONObject json = jsonParser.getJSONFromUrl(URL, params);
        return json;
    }

    public JSONObject listAllUsers() {
		List params = new ArrayList();
		params.add(new BasicNameValuePair("tag", "listall"));

		JSONObject json = jsonParser.getJSONFromUrl(URL, params);
		return json;
	}
    
}

3. Example Function Convert JSON to your Object

public User getUser(String username){
     UserFunctions uf = new UserFunctions();
     JSONObject json = uf.getUserByUserName(username);
     String res = json.getString("success");
     if (Integer.parseInt(res) == 1){
     	 JSONObject json_user = json.getJSONObject("user");

     	 return new User(json_user.getString("username"), json_user.getString("password");
     }
     return null;
}

public ArrayList getAllUser(){
	ArrayList userlist = new ArrayList ();
	UserFunctions uf = new UserFunctions();
    JSONObject json = uf.listAllUsers();
    String res = json.getString("success");
    if(Integer.parseInt(res) == 1){
    	JSONArray json_user_array = json.getJSONArray("list");
    	for (int i = 0; i < json_user_array.length(); i++) {
				JSONObject jobj = (JSONObject) json_user_array.get(i);
				userlist.add(new User(jobj.getString("username"), jobj.getString("fullname")));
		}
    }
    return userlist;
}

REFERENCES
http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/

Standard