tag:blogger.com,1999:blog-81193652382456775142023-11-16T12:29:07.026+00:00Android ThingsAndroid developer tutorials, tips, resources and thoughts.Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.comBlogger18125tag:blogger.com,1999:blog-8119365238245677514.post-75771294730018738322013-09-10T19:48:00.000+01:002013-09-10T19:48:05.918+01:00Android Database TutorialThe Android platform offers a variety of storage options you can use in your apps. If you need a structured data source, you can use an SQLite database. If you have used any SQL database in the past, such as MySQL, you will be able to use SQLite easily as you will already be accustomed to the principles and syntax involved. If you have no experience using SQL or scripting with databases, you can still pick up the essentials of using SQLite databases in your Android projects.
<br/><br/>
In this tutorial we will work through the process of using an SQLite database in Android. We will create a simple note-keeping app in which the user can add, view and delete notes. The notes will be displayed in a list, with a button to add new notes and the option to delete notes on clicking each one in the list. The tutorial will take you through the procedure of basic SQLite database implementation in Android, so you will be able to reuse the skills and techniques involved in other applications. Here is a preview of the app:
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXkc0TTWf741cQtcYVTHegbjZx6gqH_J0BsLjgiXoJsTHbVsINl9W02Od2aXHXIavLVOT0HYsaZjb0qbQlNFNWppjM9aJJJiVTIARODoGSxNs4sBHa-j15ag8Oi-MdgWYWCmacCw2K9zjO/s1600/database_app.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXkc0TTWf741cQtcYVTHegbjZx6gqH_J0BsLjgiXoJsTHbVsINl9W02Od2aXHXIavLVOT0HYsaZjb0qbQlNFNWppjM9aJJJiVTIARODoGSxNs4sBHa-j15ag8Oi-MdgWYWCmacCw2K9zjO/s1600/database_app.png" /></a></div>
<br/><br/>
For a broader overview of using SQLite in your Android apps check out the invariably excellent Vogella site, particularly this tutorial: <a href="http://www.vogella.com/articles/AndroidSQLite/article.html">Android SQLite database and content provider</a> - in this tutorial we will use a similar algorithm but will simplify some of the elements and add a little more explanation of the steps involved.
<br/><br/>
<strong>Project Setup</strong>
<br/>
Create a new Android project. You will need a blank main Activity and layout. We will also be using three additional Java classes, but their content will be relatively simple so don't worry if you have only created simple Android projects so far, this one is accessible to beginners.
<br/><br/>
<strong>Layout</strong>
<br/>
Open your app layout file. We are going to use a <em>ListActivity</em> for the app, which requires a layout containing a <em>ListView</em> with a particular ID. Using a setup like this lets you take advantage of some of the automated aspects of the Android platform, reducing the amount of functionality you have to implement yourself. Essentially we will be using the <em>ListActivity</em> and <em>ListView</em> to provide an interface to the database. Enter the following layout:
<pre class="xml" name="code">
<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:background="#FF3366CC"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:id="@+id/new_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:onClick="addNewNote"
android:text="New"
android:textColor="#FFFFFFFF" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#FFFFEE66" />
</LinearLayout>
</pre>
The layout is simple, it includes a button for the user to add a new note and a <em>ListView</em> displaying the existing notes. We specify a method to execute on clicking the button so will include it in our main Activity class later. The Java code will handle the processing required for displaying the database content in the <em>ListView</em>. For now, add the following import statements to your main Activity:
<pre class="java" name="code">
import java.util.List;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
</pre>
Make the class extend <em>ListActivity</em> for displaying the notes in a list:
<pre class="java" name="code">
public class MainActivity extends ListActivity
</pre>
<strong>Helper Classes</strong>
<br/>
Let's add all of the classes to the app. To use the SQLite database we need an <em>SQLiteOpenHelper</em> class, so add a new class to your application package, naming it "MyDataHelper" and choosing <em>SQLiteOpenHelper</em> is its superclass - the opening line of the declaration should appear as follows:
<pre class="java" name="code">
public class MyDataHelper extends SQLiteOpenHelper
</pre>
Your class will need the following import statements:
<pre class="java" name="code">
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
</pre>
We will implement the class details soon. We are also going to use a class dedicated to managing the database connection rather than doing this from the main Activity, so add another new class to your package, naming it "NoteManager". Add the following imports to the class:
<pre class="java" name="code">
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
</pre>
The final class we need is to model the notes themselves, so add another new class, naming it "Note". Let's implement this class now. Use the following declaration:
<pre class="java" name="code">
public class Note {
private long noteID;
private String noteText;
public void setNoteText(String userText){
noteText=userText;
}
public String getNoteText(){
return noteText;
}
public void setNoteID(long newID){
noteID=newID;
}
public long getNoteID(){
return noteID;
}
@Override
public String toString(){
return noteText;
}
}
</pre>
Each note will consist of a unique ID number and a text string representing the note content. These two data items are what we will add to the database for each note, so the Note class models the same data, with standard get and set methods we will use elsewhere in the app code. We implement the <em>toString</em> method because it will be used by Android when displaying the notes in the <em>ListView</em>.
<br/><br/>
<strong>Data Design</strong>
<br/>
Let's turn to the data design now. Open your <em>SQLiteOpenHelper</em> class. Add the following two instance variables to define the name and version of the database:
<pre class="java" name="code">
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "UserNotes.db";
</pre>
Define the database table name and text column name in an inner class, implementing the <em>BaseColumns</em> interface so that we can make use of its additional fields for database management:
<pre class="java" name="code">
public static class DBItem implements BaseColumns {
public static final String TABLE = "notes";
public static final String NOTE_COL = "note";
}
</pre>
Add a final instance variable to the <em>SQLiteOpenHelper</em> class in which we define the database table creation string:
<pre class="java" name="code">
private static final String CREATE_STR = "CREATE TABLE " +
DBItem.TABLE + " (" + DBItem._ID +
" INTEGER PRIMARY KEY AUTOINCREMENT, " +
DBItem.NOTE_COL + " TEXT);";
</pre>
Notice that we use the "._ID" field from the <em>BaseColumns</em> interface to define an auto-incrementing ID column in the table. Add a constructor method to the class, calling the superclass constructor:
<pre class="java" name="code">
public MyDataHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
</pre>
Now add the <em>onCreate</em> method, in which we create the table using the string we defined:
<pre class="java" name="code">
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_STR);
}
</pre>
Add standard upgrade and downgrade methods:
<pre class="java" name="code">
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DBItem.TABLE);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
</pre>
That's the <em>SQLiteOpenHelper</em> class complete!
<br/><br/>
<strong>Database Management</strong>
<br/>
Now let's turn to the database management class "NoteManager". Open it now and add two instance variables, one for the database and one for the helper class:
<pre class="java" name="code">
private SQLiteOpenHelper noteHelper;
private SQLiteDatabase noteDB;
</pre>
Add a constructor method creating an instance of the <em>SQLiteOpenHelper</em> class with the passed Context parameter:
<pre class="java" name="code">
public NoteManager(Context context){
noteHelper = new MyDataHelper(context);
}
</pre>
Next provide a method to retrieve the saved notes from the database:
<pre class="java" name="code">
public List<Note> getNotes(){
}
</pre>
Inside the method, first create a List of Note objects and open a connection to the database:
<pre class="java" name="code">
List<Note> notes = new ArrayList<Note>();
noteDB = noteHelper.getReadableDatabase();
</pre>
Execute a query for all rows and columns in the database, retrieving a Cursor which will allow us to access the data:
<pre class="java" name="code">
Cursor noteCursor = noteDB.query(MyDataHelper.DBItem.TABLE,
null, null, null, null, null, null);
</pre>
Notice that we again use a field we defined in the inner class inside the <em>SQLiteOpenHelper</em> class. Loop through the results:
<pre class="java" name="code">
while(noteCursor.moveToNext()){
}
</pre>
Inside the loop, get the ID and note text for the current rwo, again using the inner class fields:
<pre class="java" name="code">
int newID = noteCursor.getInt(
noteCursor.getColumnIndexOrThrow(MyDataHelper.DBItem._ID));
String newText = noteCursor.getString(
noteCursor.getColumnIndexOrThrow(MyDataHelper.DBItem.NOTE_COL));
</pre>
Create a Note object for the current row of the database, using the set methods we added to set the values of the ID and text:
<pre class="java" name="code">
Note newNote = new Note();
newNote.setNoteID(newID);
newNote.setNoteText(newText);
</pre>
Add the new note to the list:
<pre class="java" name="code">
notes.add(newNote);
</pre>
After the <em>while</em> loop but still inside the method, close the Cursor and database, then return the list of notes:
<pre class="java" name="code">
noteCursor.close();
noteDB.close();
return notes;
</pre>
We will be calling on this method from the main Activity to display saved notes when the app is launched. Now add a method to the data manager class for adding new notes, receiving a Note object as parameter:
<pre class="java" name="code">
public long addNewNote(Note addedNote){
}
</pre>
Inside the method, get a connection for writing to the database:
<pre class="java" name="code">
noteDB = noteHelper.getWritableDatabase();
</pre>
Create a <em>ContentValues</em> object, passing the name of the note column and the new note text to it so that we can write to the database:
<pre class="java" name="code">
ContentValues noteValues = new ContentValues();
noteValues.put
(MyDataHelper.DBItem.NOTE_COL, addedNote.getNoteText());
</pre>
Attempt to insert the new note value into the table:
<pre class="java" name="code">
long added = noteDB.insertOrThrow
(MyDataHelper.DBItem.TABLE, null, noteValues);
</pre>
Close the connection and return the ID value of the newly added column:
<pre class="java" name="code">
noteDB.close();
return added;
</pre>
We will call this from the main Activity when the user clicks the "New" button and inserts some text. Now add another new method to the data manager class, this time for deleting notes, receiving the note ID as a parameter:
<pre class="java" name="code">
public int deleteNote(long noteID){
}
</pre>
Inside the method, get a writeable database connection:
<pre class="java" name="code">
noteDB = noteHelper.getWritableDatabase();
</pre>
The delete query uses a <em>where</em> clause, in which you define the columns you want to delete. We will be deleting the column with the specified ID value. The delete method expects to receive the parameters to the <em>where</em> clause as a string array, so create one with the ID in it:
<pre class="java" name="code">
String[] params = {""+noteID};
</pre>
Attempt to execute the deletion, passing the name of the ID column and the parameters including the ID of the note we want to delete:
<pre class="java" name="code">
int deleted = noteDB.delete(MyDataHelper.DBItem.TABLE, MyDataHelper.DBItem._ID+" = ?", params);
</pre>
Close the database and return the integer value indicating how many rows have been affected:
<pre class="java" name="code">
noteDB.close();
return deleted;
</pre>
We will also call this from the main Activity. That's the database manager class complete.
<br/><br/>
<strong>Interaction</strong>
<br/>
Now we can use all of the resources we have created to display, add and delete notes. Open your main Activity class. Add three instance variables, representing the database manager, the <em>ListView</em> and a helper variable for when we delete notes:
<pre class="java" name="code">
private NoteManager noteMan;
private ListView theList;
private int notePosn;
</pre>
Inside <em>onCreate</em> your class should already have code setting the main layout as content view. After that, instantiate the database manager:
<pre class="java" name="code">
noteMan = new NoteManager(getApplicationContext());
</pre>
Retrieve the list of notes from it using the method we defined:
<pre class="java" name="code">
List<Note> existingNotes = noteMan.getNotes();
</pre>
Create an adapter so that we can map the list items to the <em>ListView</em>, passing the list and a reference to one of Android's standard list item styles:
<pre class="java" name="code">
ArrayAdapter<Note> noteAdapt = new ArrayAdapter<Note>(
this, android.R.layout.simple_list_item_1, existingNotes);
</pre>
Set the adapter on the <em>ListActivity</em>:
<pre class="java" name="code">
setListAdapter(noteAdapt);
</pre>
Get the <em>ListView</em> we added to the layout:
<pre class="java" name="code">
theList = getListView();
</pre>
Now let's add code to <em>onCreate</em> to set a listener for when users click the individual notes in the list:
<pre class="java" name="code">
theList.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View view,
int position, long id) {
}
});
</pre>
Each time the user presses a list item, the <em>onItemClick</em> method will fire. Inside it, let's create a Dialog confirming that the user wants to delete the note. First store the note ID in the class variable so that we will still be able to access it inside the Dialog code:
<pre class="java" name="code">
notePosn=position;
</pre>
Now create an Alert Dialog:
<pre class="java" name="code">
AlertDialog.Builder deleteAlert = new
AlertDialog.Builder(MainActivity.this);
deleteAlert.setTitle("Delete Note");
deleteAlert.setMessage("Do you want to delete this note?");
</pre>
Set the positive button, clicks on which will prompt the note to be deleted:
<pre class="java" name="code">
deleteAlert.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
ArrayAdapter<Note> noteAdapt = (ArrayAdapter<Note>)
MainActivity.this.getListAdapter();
Note clickedNote = (Note)noteAdapt.getItem(notePosn);
int noteDeleted = noteMan.deleteNote
(clickedNote.getNoteID());
noteAdapt.remove(clickedNote);
noteAdapt.notifyDataSetChanged();
setListAdapter(noteAdapt);
}
});
</pre>
Take a moment to look over the code here. First we retrieve a reference to the adapter, then we get the Note at the position clicked. Next we call on the <em>SQLiteOpenHelper</em> class via the database manager to delete the note by passing its ID using the Note class get method. Then we remove the Note from the <em>ListView</em> adapter, prompting an update of the displayed list so that the item is immediately removed from view.
<br/><br/>
After setting the positive button, now set a negative button so that the user can cancel if they decide not to delete:
<pre class="java" name="code">
deleteAlert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which){
dialog.cancel();
}
});
</pre>
Show the Dialog:
<pre class="java" name="code">
deleteAlert.show();
</pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgclhs7106DxlIBROmH8RcX2E2iZNDdZKdEmCVd0UUzKeEh45u98G-yeCfQx7VkrCTZ4Ra7SLn1RU4q6Y58fH45OkoIWnPxhYqhLPHHk3hrH2XG8Vfe9aqlhyphenhyphenwVXjf_WMNJbE8r9ScRERA_/s1600/database_app_delete.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgclhs7106DxlIBROmH8RcX2E2iZNDdZKdEmCVd0UUzKeEh45u98G-yeCfQx7VkrCTZ4Ra7SLn1RU4q6Y58fH45OkoIWnPxhYqhLPHHk3hrH2XG8Vfe9aqlhyphenhyphenwVXjf_WMNJbE8r9ScRERA_/s1600/database_app_delete.png" /></a></div>
That's us finished with the <em>onCreate</em> method. Now add the method we specified as <em>onClick</em> attribute for the "New" button in the layout:
<pre class="java" name="code">
public void addNewNote(View v){
}
</pre>
We will use another Dialog, this time with an editable text field in it so that the user can enter a new note. Inside the new method, create the Dialog:
<pre class="java" name="code">
AlertDialog.Builder addAlert = new AlertDialog.Builder(this);
addAlert.setTitle("New Note");
addAlert.setMessage("Enter your note:");
</pre>
Add the editable text field:
<pre class="java" name="code">
final EditText noteIn = new EditText(this);
addAlert.setView(noteIn);
</pre>
Set the behaviour for when the user clicks the OK button after entering their new note:
<pre class="java" name="code">
addAlert.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String noteInput = noteIn.getText().toString();
Note inputNote = new Note();
inputNote.setNoteText(noteInput);
long addedID = noteMan.addNewNote(inputNote);
inputNote.setNoteID(addedID);
ArrayAdapter<Note> noteAdapt = (ArrayAdapter<Note>)
MainActivity.this.getListAdapter();
noteAdapt.add(inputNote);
}
});
</pre>
As you can see this uses a similar algorithm to the delete functionality. We get the entered text, create a new note using it and add it using the data manager class. The data manager method returns the ID of the new row added to the database as a long number, which we then set as ID using the Note object set method. Finally we update the display by adding the Note to the adapter.
<br/><br/>
After setting the positive button, now set a negative one for cancelling:
<pre class="java" name="code">
addAlert.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which){
dialog.cancel();
}
});
</pre>
Show the Dialog:
<pre class="java" name="code">
addAlert.show();
</pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR_WgfL8T1RjB2Pkn36XU36A4zME3PcwPi_iCCrB4Jf7SBIcijTGLN64YY-5G481kJYXZZX9uMaV3ODTCwy5MeGsQUw5RBvxqvTpIoV0bmGoklKQS4GZgSsxq4trclQh_rLPD93rwzOJxp/s1600/database_app_new.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR_WgfL8T1RjB2Pkn36XU36A4zME3PcwPi_iCCrB4Jf7SBIcijTGLN64YY-5G481kJYXZZX9uMaV3ODTCwy5MeGsQUw5RBvxqvTpIoV0bmGoklKQS4GZgSsxq4trclQh_rLPD93rwzOJxp/s1600/database_app_new.png" /></a></div>
That's the database-powered note-keeping app complete! You should be able to run yours now to see it in action. If you want to explore database functionality with SQLite on Android further, try adding the ability to edit notes and to update them.
<br/><br/>
<strong>References</strong>
<ul>
<li><a href="http://developer.android.com/training/basics/data-storage/databases.html">Android Developers: Saving Data in SQL Databases</a></li>
<li><a href="http://developer.android.com/reference/android/database/sqlite/package-summary.html">Android Developers: android.database.sqlite</a></li>
</ul>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com4tag:blogger.com,1999:blog-8119365238245677514.post-50389598193934919492013-09-02T17:07:00.001+01:002013-09-02T17:07:21.042+01:00Learning Java for AndroidI really enjoy writing tutorials on Android development, particularly where the aim is to provide a foundation for future learning and where the reader may have little or no previous programming experience. I love programming and believe anyone can learn to do it - the opportunity to ignite the same excitement in other people makes it a real privilege. <br />
<br />
I've been thinking recently about writing an eBook on Android development, perhaps on learning Java for Android application development. There seem to be one or two on the eBook market already covering the topic, but they either don't focus specifically on it or go into a lot more detail than I think is really necessary to get someone started using Java to create Android apps.<br />
<br />
To get started in Android development with no prior Java experience, there are a few key concepts and techniques to learn, but you should be able to create your first Android app fairly quickly. For this reason, I'm thinking I might publish a small-ish eBook (probably for Kindle) on getting to grips with the essential features of Java necessary for creating initial Android apps.<br />
<br />
The eBook would probably not cover advanced Java programming topics, focusing instead on learning what's necessary to get a good start on the Android platform. I would also try to restrict the content to what you need to get started creating basic apps, steering away from the more professional aspects, hopefully making it more accessible/ less intimidating and obviously a little lower in cost than most of the existing titles.<br />
<br />
Topics would include the basics of object oriented development, expanding on what I covered in this post: <a href="http://stackoverflow.com/questions/3496191/should-i-learn-java-before-learning-android">Object Oriented Concepts for Android Development in Java</a>. I would also cover the main Java classes Android beginners are likely to use on the platform, as well as essential features of the language such as control structures and data storage. Ideally the eBook would make Android development accessible to people with no Java experience at all, and hopefully even to people who don't have any background in programming or development.<br />
<br />
Although there is of course more to Android development than Java programming, the other technologies used on the platform (XML, SQL etc) involve a lot less complexity and are therefore easier to pick up. Java is best learnt with a conceptual approach, which can benefit from textual explanation more than some other programming topics.<br />
<br />
It seems that the resources dedicated to getting people started in Android development focus exclusively on the Java syntax and structures necessary to create apps rather than on the conceptual side of things. Learning these features of Java can have an enormous impact on your ability to build apps efficiently and have a rewarding experience while you're at it. Learning only the parts of a language that are necessary is also a recipe for poorly built applications as well as a frustrating development process.<br />
<br />
If anyone who reads or comes this blog has any input in terms of what they feel would be a useful topic for an eBook, topic to cover in an eBook or even in a blog post on Android development, please do feel free to leave comments. Any feedback is appreciated.<br />
<br />Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com1tag:blogger.com,1999:blog-8119365238245677514.post-25866430730939013152013-08-13T15:43:00.001+01:002013-08-13T15:43:38.461+01:00Barcode Scanning in Android AppsBarcode scanning is one of the most potentially useful resources you will come across on the Android platform. The ZXing (Zebra Crossing) project is bar far the easiest and most effective way to implement barcode scanning for most development purposes. Since the project is open source, you can either use the code within it to implement your own custom scanning functions or can access the library classes via Intent, leaving the details up to the ZXing classes.
<br/><br/>
ZXing can scan numerous barcode formats in use on a variety of products, including EAN/ ISBN, UPC, QR codes, Data Matrix, Aztec and more. The resource is implemented in Java, with Android-specific classes available for quick use in your own projects.
<br/><br/>
<b>Usage</b>
<br/><br/>
For a detailed introduction to using barcode scanning in Android apps, see this tutorial I wrote for Mobiletuts+: <a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-create-a-barcode-reader/">Create a Barcode Reader</a> and this series on creating a book scanner app for more of a real-world example: <a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-create-a-book-scanning-app/">Create a Book Scanning App</a>. For a comprehensive reference, see the ZXing docs: <a href="http://code.google.com/p/zxing/wiki/ScanningViaIntent">Scanning Via Intent</a>.
<br/><br/>
The simplest way to include scanning functions in your apps is by Intent. You simply copy the <a href="http://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java">Intent Integrator</a> and <a href="http://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentResult.java">Intent Result</a> classes into your app and call on them in your own classes.
<br/><br/>
To use the ZXing integration classes in your app, import them to the Activity class you want to access them in, for example the following if you use the default package names:
<pre class="java" name="code">
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
</pre>
You can then launch the scanner in your Activity class as follows:
<pre class="java" name="code">
IntentIntegrator zxingIntegrator = new IntentIntegrator(this);
zxingIntegrator.initiateScan();
</pre>
If the user does not have the ZXing barcode scanner installed on their device, they will be prompted to download it from Google Play at this point, so you don't have to carry out any checking of your own. When you initiate a scan, you can optionally pass a parameter indicating the types of barcode you want to scan - the parameter should be a Collection of Strings.
<br/><br/>
You can then retrieve the results of the user's scanning operation inside the <em>onActivityResult</em> method for your class:
<pre class="java" name="code">
IntentResult scannedResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
</pre>
The Intent Result object will now provide access to the content and format of the returned scan data if there is any:
<pre class="java" name="code">
scannedResult.getContents();
scannedResult.getFormatName();
</pre>
<b>Options</b>
<br/><br/>
While using the integration classes is by far the simplest way to utilise the ZXing functionality, there may be times when you need to implement your own bespoke scanning functions. If so, you can download the <a href="http://code.google.com/p/zxing/downloads/list">source code</a>. It's probably only advisable to do this if you have no other option, since using the integration classes gives your app access to the continual updates within the ZXing app without you having to update your own code.
<br/><br/>
<b>
Applications</b>
<br/><br/>
There are lots of potential applications of barcode scanning in Android, from inventory and warehouse functions to shopping apps. Your apps need to respond to the data within a barcode in a relevant way, so your code must examine the scan results before attempting to use them in further processing, for example opening a URL in the browser.
<br/><br/>
As usual, Stack Overflow has the answers to lots of common questions and problems with <a href="http://stackoverflow.com/search?q=zxing">ZXing</a>.Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com2tag:blogger.com,1999:blog-8119365238245677514.post-26202270902552255232013-08-08T19:04:00.000+01:002013-08-08T19:04:51.915+01:00Using the SeekBar Control in Android AppsIn this tutorial we will work through the process of using the SeekBar control in an Android app. The SeekBar control allows users to select a numerical amount using a slider control. Using the SeekBar is straightforward, you can add one to an XML layout file and retrieve the user input in your Java Activity classes.
<br/><br/>
To demonstrate the process of using the SeekBar, we will add one to a Dialog control launched on clicking a user interface item. Here is the end result:
<br/><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr4TywYNPz1zbkwA4OORGF5sk-LKfkucPZH7hqu0Ib288pp93wJMhhzKKnLrlAlPz8KWg0qO85-DeeXHthwanr2KZdkIpednOXSHethkk8znwZ2IgG0xm4WtUREqIU9XllHcCFiBOZNO6b/s1600/seekbar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr4TywYNPz1zbkwA4OORGF5sk-LKfkucPZH7hqu0Ib288pp93wJMhhzKKnLrlAlPz8KWg0qO85-DeeXHthwanr2KZdkIpednOXSHethkk8znwZ2IgG0xm4WtUREqIU9XllHcCFiBOZNO6b/s1600/seekbar.png" /></a></div>
Add the SeekBar to an XML layout in your app as follows:
<pre class="xml" name="code">
<SeekBar
android:id="@+id/level_seek"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
</pre>
To include this in a basic layout you could use the following, saved as "level_layout.xml" for use with the below Java code:
<pre class="xml" name="code">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView android:id="@+id/level_txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="5dp"
android:textStyle="bold"
android:text="100%"/>
<SeekBar android:id="@+id/level_seek"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
<Button android:id="@+id/level_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"/>
</LinearLayout>
</pre>
The user selection can be retrieved when they click the button and the TextView can update as they move the slider control, to reflect the current amount selected, which in this tutorial will be a percentage value.
<br/><br/>
Now in an Android Activity class, you can set the initial value and retrieve the chosen user value. To use it in a Dialog, which is a typical usage of the slider control in many application UIs, add the following to a click listener <em>onClick</em> block in an Activity class for a button or other control you want the SeekBar to appear for:
<pre class="java" name="code">
final Dialog levelDialog = new Dialog(this);
levelDialog.setTitle("Select level:");
levelDialog.setContentView(R.layout.level_layout);
</pre>
Retrieve references to the TextView and SeekBar items in the layout defined above:
<pre class="java" name="code">
final TextView levelTxt = (TextView)levelDialog.findViewById(R.id.level_txt);
final SeekBar levelSeek = (SeekBar)levelDialog.findViewById(R.id.level_seek);
</pre>
Set the maximum value for the SeekBar:
<pre class="java" name="code">
levelSeek.setMax(100);
levelSeek.setProgress(100);
</pre>
We are using 100 as the maximum since the SeekBar is going to set a percentage. Next set up a listener for changes on the SeekBar control:
<pre class="java" name="code">
levelSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//change to progress
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
levelTxt.setText(Integer.toString(progress)+"%");
}
//methods to implement but not necessary to amend
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
</pre>
You can of course implement the start and stop tracking methods to tailor user interaction with the SeekBar in your app. All we do here is update the TextView with the current level as the user slides the control up or down. Next retrieve a reference to the "OK" button we added to the layout:
<pre class="java" name="code">
Button okBtn = (Button)levelDialog.findViewById(R.id.level_ok);
</pre>
Set up a click listener for the button:
<pre class="java" name="code">
okBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//respond to level
int chosenLevel = levelSeek.getProgress();
levelDialog.dismiss();
}
});
</pre>
In this <em>onClick</em> method you can add whatever code you need to respond to the user's chosen level using the retrieved integer value. The method also dismisses the Dialog. Finally, still inside the <em>onClick</em> method, show the Dialog:
<pre class="java" name="code">
levelDialog.show();
</pre>
Your app should now have the ability to let users set levels using this intuitive control, which almost all smartphone users are well accustomed to.
<br/><br/>
Further Resources:<br/>
<a href="http://developer.android.com/reference/android/widget/SeekBar.html">Android Developers: SeekBar Class</a>
<br/>
<a href="http://www.techrepublic.com/blog/android-app-builder/androids-seekbar-your-way/">TechRepublic: Android's SeekBar your way</a>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-62234789557563667832013-07-29T15:26:00.001+01:002013-08-08T12:35:30.595+01:00Android: Defining Animation in Java on User InteractionIn this tutorial we will demonstrate using a set of animations on an Android view, with the animation prompted by user interaction. We will include an Image View in the app layout, starting the animations when the user clicks it. We will make two animations run concurrently using an Animation Set. Rather than defining the animations in XML as resources, we will implement the details in Java. I've written about some of the other approaches to animation in Android for Mobiletuts+, see these more detailed guides:
<br />
<ul>
<li><a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-creating-a-simple-tween-animation/">Creating a Simple Tween Animation</a></li>
<li><a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-quick-tip-creating-frame-animations/">Creating Frame Animations</a></li>
<li><a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-creating-a-simple-property-animation/">Creating a Simple Property Animation</a></li>
</ul>
This tutorial indicates some of the alternative options you can choose from when implementing animations in your Android projects.
<br /><br/>
<h3>
Setup Layout and Drawables</h3>
In your app layout, you can use any view you want to animate, for example, the following Image View:
<br />
<pre class="xml" name="code">
<imageview
android:background="@drawable/spin_pic"
android:id="@+id/spinView"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
</imageview></pre>
The background drawable can be any shape you like, for example the following, saved in the app drawables as "spin_pic.xml":
<br />
<pre class="xml" name="code">
<shape android:dither="true" android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="45" android:endcolor="#ffff0000" android:startcolor="#ff0000ff">
<size android:height="100dp" android:width="100dp">
</size></gradient></shape>
</pre>
The shape is a circle with a linear gradient in it. You can include it in any layout you choose.
<br /><br/>
<h3>
Java Activity</h3>
In your Java Activity class, set the layout as normal. Your class will need the following imports:
<br />
<pre class="java" name="code">import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
</pre>
Retrieve a reference to the view you want to animate in <i>onCreate</i>:
<br />
<pre class="java" name="code">ImageView spinBtn = (ImageView)findViewById(R.id.spinView);
</pre>
Set the class up to act as click listener for the Image View:
<br />
<pre class="java" name="code">spinBtn.setOnClickListener(this);
</pre>
For this your Activity class must implement the <i>OnClickListener</i> interface as follows, but with your own class name:
<br />
<pre class="java" name="code">public class YourActivity extends Activity implements OnClickListener
</pre>
Add an <i>onClick</i> method to the class and check for the Image View:
<br />
<pre class="java" name="code">public void onClick(View v){
if(v.getId()==R.id.spinView){
//respond to click
}
}
</pre>
Alter the code if your view has a different ID. Inside the conditional block you can start the animation.
<br /><br/>
<h3>
Animate</h3>
Now you can animate your view when it is clicked. We will be spinning and fading the view at the same time. In the <i>if</i> block you created in <i>onClick</i> for the view you want to animate, first create a Rotate Animation:
<br />
<pre class="java" name="code">RotateAnimation rotateAnim = new RotateAnimation
(0f, 360f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
</pre>
The first two parameters represent the number of degrees to rotate the view from and to - we will rotate it one full circle. The second two pairs of parameters represent the pivot points to rotate on, with the first pair representing the X pivot value type then the value and the second two doing the same for the Y value - this code defines the centre of the view on both axes.
<br /><br/>
Next define an Alpha Animation to fade the view out as it rotates:
<br />
<pre class="java" name="code">AlphaAnimation alphaAnim = new AlphaAnimation(1.0f, 0.0f);
</pre>
We will fade the view from full alpha to invisible. Next create an Animation Set so that we can apply both animations to the same view:
<br />
<pre class="java" name="code">AnimationSet animSet = new AnimationSet(true);
</pre>
The <i>true</i> parameter specifies that the same interpolator should be used for all animations in the set. Now specify the animation set properties:
<br />
<pre class="java" name="code">animSet.setInterpolator(new AccelerateInterpolator());
animSet.setDuration(3000);
animSet.setRepeatCount(0);
animSet.setFillAfter(true);
</pre>
You could set the properties for the animations individually - setting them on the set applies them to all animations within it. We will accelerate the animation, let it elapse over 3000 milliseconds, only carry it out once and retain the end state rather than letting the view jump back to its original state after the animation is complete, which is the default behaviour.
<br />
Add the two animations to the set:
<br />
<pre class="java" name="code">animSet.addAnimation(rotateAnim);
animSet.addAnimation(alphaAnim);
</pre>
Finally, start the animation on the view:
<br />
<pre class="java" name="code">v.startAnimation(animSet);
</pre>
Run your animation to see the result:
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyog5YLyKH0efN-HaXTw5flWuUfuGa-Kv-LUFP30jTnUGN9rJan3wCm7aSBaiUrh4VMkctgVsY7n7-KAKX4WUGzr7emPGhBH1VwBmryoupppTqntX1MrnefZiNYRq90HP9jGNxtW6xQ3VT/s1600/anim1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyog5YLyKH0efN-HaXTw5flWuUfuGa-Kv-LUFP30jTnUGN9rJan3wCm7aSBaiUrh4VMkctgVsY7n7-KAKX4WUGzr7emPGhBH1VwBmryoupppTqntX1MrnefZiNYRq90HP9jGNxtW6xQ3VT/s1600/anim1.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWM44K8oXN5SuoqsvALAhMPLUhVWbJ3psNMm0qN_qEBmrjp85-WpWbV3YnbTqpPRz60urUCzFUC7XCCA7UEmiNnYwirjjm2I194XteNxWIV1BlVM1uBjc7GkAP1KMWFP7Pp0z_9uRTnRqu/s1600/anim2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWM44K8oXN5SuoqsvALAhMPLUhVWbJ3psNMm0qN_qEBmrjp85-WpWbV3YnbTqpPRz60urUCzFUC7XCCA7UEmiNnYwirjjm2I194XteNxWIV1BlVM1uBjc7GkAP1KMWFP7Pp0z_9uRTnRqu/s1600/anim2.png" /></a></div>
The view spins and fades on clicking, eventually disappearing completely.
<br /><br/>
<h3>
Resources</h3>
The official Android Developer Guide runs through the various options you have in animating application elements: <a href="http://developer.android.com/guide/topics/graphics/index.html">Animation and Graphics</a>
Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-92134911405963976522013-03-06T20:34:00.000+00:002013-03-06T20:40:24.247+00:00Jump Into Android: Create A Battery Level Widget<b><i>PLEASE NOTE: This tutorial was originally published (some time ago) on the Tuts+ marketplace, which is no longer operating. I haven't had a chance to update the tutorial just yet, but the existing code may still be useful...</i></b><br/><br/>
Getting started with Android development can be an arduous process. It's difficult to motivate yourself to continue learning a new topic when you feel you're not learning anything particularly useful. In this tutorial we'll aim to equip you with practical, re-usable skills and knowledge by creating an Android battery level widget. As well as getting to grips with the basics of building widgets, we'll cover a range of useful techniques for Android, including:<br />
<ul>
<li>handling receivers in widget apps</li>
<li>creating the manifest for an Android widget</li>
<li>using resources in Android widgets, including shape drawables, XML values, colors and layouts</li>
<li>using Java conditionals, including chained if/ else and switch/ case statements</li>
<li>creating and using helper methods in Java/ Android classes</li>
<li>using constants and class instance variables</li>
<li>extending Java/ Android classes using inheritance, including overriding methods</li>
</ul>
If you haven't created a single Android project yet, this tutorial might
be a bit advanced, but if you've at least had a go at the Hello Android
or another basic app project and have initial familiarity with Java,
this tutorial should be accessible to you. The text runs through each
step in turn and the source code is provided for future reference. The
Java source code files are annotated throughout, and both Java and XML
are explained in detail within the text. Some of the steps are pretty
detailed, but try to focus on each one in turn and not worry about how
fast you are progressing through the tutorial as a whole. We will
intentionally be exploring the techniques in detail, so that you are
more likely to retain the skills into the long term. The tutorial has
lots of images to help you make sure you understand the processes
involved.<br /><br/>
<h3>
What Are We Making? </h3><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5ztgVl1TWHvM0Y6slPkcqpEKSyVX8Y3iycw8gRA22KMmZ92UkYcwO6IR8A3dFF0QJWQv_bgGjFAtXj2-OBYX2ZbGr1OXuUUY5OmPIndmuE-YnBgBMR5QEotijdiUOYUUMchdsyiQoU6pa/s1600/homescreen_widget.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5ztgVl1TWHvM0Y6slPkcqpEKSyVX8Y3iycw8gRA22KMmZ92UkYcwO6IR8A3dFF0QJWQv_bgGjFAtXj2-OBYX2ZbGr1OXuUUY5OmPIndmuE-YnBgBMR5QEotijdiUOYUUMchdsyiQoU6pa/s400/homescreen_widget.jpg" width="240" /></a></div>
<br />
<br />
In this tutorial, we're going to make a battery level widget. Android widgets are released, downloaded and installed in the same way as any other app. However, to launch and use a widget, the user must add it to their homescreen, normally by long-pressing an empty space and choosing "Widgets" before browsing through the list. The widget is going to give a visual and textual indicator of the current battery level. To implement this, we need to define various aspects of the application in XML code, including the visual elements. We will also create a Java class extending a standard Android class to implement the widget's functionality, i.e. updating its appearance to reflect the battery level when it changes.<br />
<br />
There are various aspects of the widget that you can alter to suit yourself, and the text will outline some of the areas you have alternative options for. You can choose your own names for classes, variables and resources at any stage, but you may find it easiest to start by following the steps exactly, then make any changes you want later on. This tutorial assumes you are using Eclipse to develop your Android projects, but if you are using another IDE you should still be able to follow the steps. Finally, don't feel under any pressure to complete the steps in one session - work on the project at a pace you feel comfortable with and feel free to go back over any steps you're unclear on. <br /><br/>
<h3>
Step 1: Create a New Android Project </h3><br/>
OK, let's get stuck in. Create a new project for your widget in Eclipse or your chosen IDE. In Eclipse, choose File, New, Project. Open the Android folder and select Android Project, then click Next.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUPqPsM6hShPLxTBrPuiPeOS2Z8AHWVP7cFI8FYm8Bl98j12nXjPI876u7vDjGBFErNlRohnLo4Yqvvu_rex-bOaNgx97J7t4pk4T5o_r4GoTaJQcuevArkM1i5MWj5fdygl8QQakJEfFG/s1600/new_project.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="387" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUPqPsM6hShPLxTBrPuiPeOS2Z8AHWVP7cFI8FYm8Bl98j12nXjPI876u7vDjGBFErNlRohnLo4Yqvvu_rex-bOaNgx97J7t4pk4T5o_r4GoTaJQcuevArkM1i5MWj5fdygl8QQakJEfFG/s400/new_project.png" width="400" /></a></div>
<br />
Enter your project details. Insert a name for your project, e.g. "LovelyBattery", select "create new project in workspace" and click Next.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqO9YI1IfGBwVV2vbIPzbjetEbC5qRBew7sCbvTACxBL_l4DCFMDsZDWvNdx4mVrexzLPk57fhVUNPK3l738ZDAkWqY5xfGIoYCCM3gxbHkGKqmmzZcORvlmJRd1ZZQj-tQ6pMHsFWObOQ/s1600/create_project.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqO9YI1IfGBwVV2vbIPzbjetEbC5qRBew7sCbvTACxBL_l4DCFMDsZDWvNdx4mVrexzLPk57fhVUNPK3l738ZDAkWqY5xfGIoYCCM3gxbHkGKqmmzZcORvlmJRd1ZZQj-tQ6pMHsFWObOQ/s400/create_project.png" width="357" /></a></div>
Choose your SDK build target, then click Next. You can change this later so don't worry too much about what API level you choose at this stage.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfhwgWo_6lwANsblXY6vM3hak0BpZTwHQXzoE-Q_pE1Kc3MRgccluflHr4hVsD-cv9599bGyU4WJ4RE3lNXoBLIeOZlMBLcMz6eEomgAYaeBJTsAjtGaN1hWY135f2uczGKfq_hNbuwUmQ/s1600/choose_sdk.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfhwgWo_6lwANsblXY6vM3hak0BpZTwHQXzoE-Q_pE1Kc3MRgccluflHr4hVsD-cv9599bGyU4WJ4RE3lNXoBLIeOZlMBLcMz6eEomgAYaeBJTsAjtGaN1hWY135f2uczGKfq_hNbuwUmQ/s400/choose_sdk.png" width="359" /></a></div><br/>
Enter your application info. Your project name should be automatically filled in, but you need to enter the package you want to use for your widget, e.g. "com.yourdomain.battery". Uncheck the Create Activity checkbox, as we don't need this for a widget app. Choose any other settings you want and click Finish. Your new project should appear in the Eclipse Package Explorer.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWDCITXuoPKJ9ofvSdCCREfuCPsJmS-3uqjGPRORDywfrxlAOP401r_IUx87g26lMuwo1IgZfy2d-5vKqo0ZvPFPrFQkwGfgQ2uwhGf41dghQJ_edtq0cgG2sLtB50XILcdOytKIirbxin/s1600/app_info.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWDCITXuoPKJ9ofvSdCCREfuCPsJmS-3uqjGPRORDywfrxlAOP401r_IUx87g26lMuwo1IgZfy2d-5vKqo0ZvPFPrFQkwGfgQ2uwhGf41dghQJ_edtq0cgG2sLtB50XILcdOytKIirbxin/s400/app_info.png" width="358" /></a></div>
<br />
<h3>
Step 2: Edit your Project Manifest</h3><br/>
You need to instruct the system to treat your app as a widget and set it up for updates. Open your application Manifest file, which you should see inside the package directory.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmnUwOGcHhAE-D3kfnhSoX_oiRGjabNMkLg0WtNhpmVvx4JTmmq5M5IXfFfN28mJArDAzAyVqc5DzpxxZayt6wB8fXnAh8mU9I2AiXstfgeI1NvuHg0WmcOmG1Z3Q_McmWeu4H3ytc10oG/s1600/app_manifest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmnUwOGcHhAE-D3kfnhSoX_oiRGjabNMkLg0WtNhpmVvx4JTmmq5M5IXfFfN28mJArDAzAyVqc5DzpxxZayt6wB8fXnAh8mU9I2AiXstfgeI1NvuHg0WmcOmG1Z3Q_McmWeu4H3ytc10oG/s400/app_manifest.png" width="400" /></a></div>
<br />
To access the XML code for your Manifest, click the tab at the bottom of the code editor window containing it, which should be named "AndroidManifest.xml". Creating a Manifest for a widget is slightly different to the process used for normal apps, which are launched through the main user device menu. Use the following code for your Manifest, adding it after the XML declaration on the first line:<br />
<pre class="xml" name="code"><manifest android:versioncode="1"
android:versionname="1.0"
package="com.yourdomain.battery"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minsdkversion="3"></uses-sdk>
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<receiver android:name="LovelyBatteryWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/battery_widget_info"></meta-data>
</receiver>
</application>
</manifest>
</pre>
If you used a different package, alter the package attribute of the manifest element accordingly. Your IDE will display error messages when you first enter this code, but don't worry, they'll disappear when we add the next elements. You should see two error messages initially because we have not yet added the drawable icon file or the XML metadata file.
<br />
<br />
It's worth understanding the content of the Manifest to give yourself a clearer grasp of how the Android platform handles widgets. The main difference between this and a normal app Manifest is what's going on inside the application element. Inside this element is a receiver element, which indicates a class name, in this case "LovelyBatteryWidget". This class will handle updating the widget. The receiver element also contains an intent filter and metadata. The intent filter specifies that the widget should be able to receive updates. The meta-data section indicates an XML file which will contain configuration details for the widget.
<br />
<br />
Don't worry if this seems a lot to take in at first, as we'll revisit some of these elements as we add the code necessary to build the widget. The best way to learn is by using the code yourself.
<br /><br/>
<h3>
Step 3: Create the Widget Metadata</h3><br/>
As we saw in the Manifest, the widget app uses an XML metadata file. You can see from its entry in the Manifest that the file is going to be named "battery_widget_info" and saved in the XML resources folder, hence the "@xml/battery_widget_info" attribute. You can alter the name of the file when you create it if you like, just make sure it matches the entry in the Manifest.
<br />
<br />
Create an XML resource folder. Browse to your application package "res" folder and create a new folder inside it by right-clicking on it (Ctrl+click on Mac), choosing New, then Folder. Enter "xml" as the folder name and click Finish. It should appear in your app directory structure. Create your XML metadata file inside this new folder by right-clicking it, choosing New, then File. Enter "battery_widget_info.xml" as the file name and click Finish.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCOz4HLXdTjbtwliM3hnsaPXvMC3TcwFYw58wJBS5wLzNVOuVIKPrH4a3W40mtIXJsWKjYrgPh-ZK6XqJAPY85rYm65Xy4LMKx3EYRKx_4AmnWAIYh5k1wbV_VNKEAVAr0vo9CszUfNDae/s1600/xml_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCOz4HLXdTjbtwliM3hnsaPXvMC3TcwFYw58wJBS5wLzNVOuVIKPrH4a3W40mtIXJsWKjYrgPh-ZK6XqJAPY85rYm65Xy4LMKx3EYRKx_4AmnWAIYh5k1wbV_VNKEAVAr0vo9CszUfNDae/s400/xml_file.png" width="345" /></a></div>
<br />
Your file should appear inside the new folder and should automatically open, although it should be empty at first. Again, don't worry if your IDE displays error messages.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyQqRxqGX9iWPV-Z9hFqxCHUhxStuQeRoENFyIASFGRXCIX3e2X_rRTPUR7mEYJL6Dei5ngKDEO6ELM9HtCYWhfSlIiO-bOpNYFH8h7TB7gA9YF7YsvmUF7n-WkxnQbBWNlbWpEvh2-8DQ/s1600/open_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyQqRxqGX9iWPV-Z9hFqxCHUhxStuQeRoENFyIASFGRXCIX3e2X_rRTPUR7mEYJL6Dei5ngKDEO6ELM9HtCYWhfSlIiO-bOpNYFH8h7TB7gA9YF7YsvmUF7n-WkxnQbBWNlbWpEvh2-8DQ/s400/open_file.png" width="400" /></a></div><br/>
Now we need to create the XML metadata. Enter the following inside your new file:<br />
<pre class="xml" name="code"><appwidget-provider
android:initiallayout="@layout/battery_widget"
android:minheight="72dp" android:minwidth="72dp"
android:updateperiodmillis="1800000"
xmlns:android="http://schemas.android.com/apk/res/android">
</appwidget-provider>
</pre>
This file indicates the basic configuration details for your widget. The minimum height and width indicate a widget that accommodates a single cell on the user's homescreen, however you can create widgets that occupy multiple cells. In general, you can use around 74 density-independent pixels for each cell in your widget, but we subtract 2 to allow for margins or errors. The "updatePeriodMillis" attribute indicates how often you want your app to update in milliseconds. The value we are using is the shortest period allowed on the Android platform, which is 30 minutes represented in milliseconds. Finally, the "initialLayout" attribute indicates a layout file to use when displaying the widget. Again, your IDE may indicate errors because we have not yet added the specified layout file.<br /><br/>
<h3>
Step 4: Create the Widget Layout</h3><br/>
Create a new file in your application layout folder by right-clicking it ("res/layout"), choosing New, then File. Enter the name you used in your metadata file with ".xml" as the extension, "battery_widget.xml" if you used the code above. Click Finish and your file will appear in the layout folder, as well as opening automatically in the Eclipse code editor.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirmOp7-AJiCaMJV-_3ncpux-bDonyu7z3_M6dYPZ4evNpI3F_SYJjxUrioUyckNCS3_951pK1xGD0oOQCaSiHT3yKM8vEk9kdmcMbAeiDCqLDwSuy-7BWJadSAw5jVBWOOFJiU7FSy7_oT/s1600/layout_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirmOp7-AJiCaMJV-_3ncpux-bDonyu7z3_M6dYPZ4evNpI3F_SYJjxUrioUyckNCS3_951pK1xGD0oOQCaSiHT3yKM8vEk9kdmcMbAeiDCqLDwSuy-7BWJadSAw5jVBWOOFJiU7FSy7_oT/s400/layout_file.png" width="345" /></a></div>
<br />
In Eclipse, you can view and interact with layout files using the graphical editor, but this is not normally particularly useful for widgets, so switch to XML by choosing the "battery_widget.xml" tab at the bottom of the code editor pane. Enter XML code for your layout, starting with the following outline:
<br />
<pre class="xml" name="code"><linearlayout
android:background="@drawable/batt_bg"
android:id="@+id/battery"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
</linearlayout>
</pre>
We will use a Linear Layout to display visual elements one after another vertically. Between the Linear Layout tags we will place the visible elements within the widget. The layout has an ID attribute so that we can reference it from elsewhere in the application code. The layout also has a background image drawable indicated, which we will create later. You can create your own visual design if you like, but for this tutorial we will create a widget with a text indication of the battery level at the top, then a visual area representing the level using ten bars. Add the following code between your opening and closing Linear Layout tags:
<br />
<pre class="xml" name="code"><textview android:gravity="center" android:id="@+id/text_level" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="level%" android:textsize="10dp" android:textstyle="bold"></textview>
<imageview android:background="@drawable/top_line" android:layout_gravity="center" android:layout_height="wrap_content" android:layout_marginbottom="1dp" android:layout_width="wrap_content"></imageview>
</pre>
This code adds a Text View item at the top of the widget, followed by a horizontal line, represented as a drawable shape which we will create later. The Text View has an ID so that we can refer to it within the application, along with basic properties and some initial text to display. The Image View also sets several basic properties including a margin at the bottom.<br />
<br />
Next we need to create ten Image Views, one for each bar within the battery graphic. Add the following code after the last section you added:<br />
<pre class="xml" name="code"><imageview android:id="@+id/bar10" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar9" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar8" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar7" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar6" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar5" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar4" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar3" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar2" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
<imageview android:id="@+id/bar1" android:layout_gravity="center" android:layout_height="5dp" android:layout_width="wrap_content" android:visibility="invisible"></imageview>
</pre>
Again, each of the ten bars has an ID attribute for reference within the application code. As well as setting basic properties, the bars are initially set to be invisible. Within the Java class handling the widget updates, we will add code to display the bars in a way that reflects the battery level. We will also create drawable resources to represent the bars at low, medium and high level - and to indicate partial levels.
<br /><br/>
<h3>
Step 5: Create the Widget Drawables</h3><br/>
The battery widget is going to contain several different image resources, which we will save in the "res/drawables" folder. Depending on your own setup, your project may contain three drawable folders, for low, medium and high definition screen displays, named "drawable-hdpi", "drawable-ldpi" and "drawable-mdpi". You can use these to specify different drawable resources for the different resolutions, but you may not need to do this depending on your widget design. For this tutorial, we'll use one drawables folder for all devices, but you can of course change this. If you want to use the three separate folders, simply repeat the process for each item listed, placing a copy of each drawable resource in each of your drawable folders.
<br />
<br />
First, let's create the application icon. You may remember that we specified a drawable file named "icon" in the widget Manifest, so we now need to create this file. You can create an image file in a format such as JPEG or PNG if you like, but for this tutorial we will create the image in XML, as this is a good general Android skill to develop. If you want to use a graphic file created in another program, simply save it with "icon" as the file name, e.g. "icon.jpg", then copy it to the drawables folder(s) in your application package in the Eclipse workspace. For the XML approach, in your drawables folder(s), create a new XML file by selecting the folder, right-clicking, choosing New, File, entering "icon.xml" and clicking Finish.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWAZwVPT9Ne8jxRPxa0AZ61jNIvelV1wYqkyj-Rjm75xhq9eSm3ZJvsUJdoaxNrOLXrEOtPHLm3K787KjuSMQLWc6ZlU069plQ3lE__19HAGtr7-jUVkfSqf4Ovpk57nnJ46PxUR6wpw36/s1600/icon_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWAZwVPT9Ne8jxRPxa0AZ61jNIvelV1wYqkyj-Rjm75xhq9eSm3ZJvsUJdoaxNrOLXrEOtPHLm3K787KjuSMQLWc6ZlU069plQ3lE__19HAGtr7-jUVkfSqf4Ovpk57nnJ46PxUR6wpw36/s400/icon_file.png" width="346" /></a></div><br/>
Our widget app icon is going to be pretty simple, but you can make it as complex as you like. Add the following code to your icon XML file to begin with:
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_green" android:endcolor="@color/dark_green" android:startcolor="@color/dark_green"></gradient>
<size android:height="68dp" android:width="68dp"></size>
<stroke android:color="@color/dark_red_alpha" android:width="2dp"></stroke>
</shape>
</pre>
This code defines an icon image with a green gradient in the middle and a red stroke around it. The image is defined as a Shape Drawable, which is a rectangle. Inside the shape we define the gradient and stroke. The code contains references to color resources, which we will create soon. The final image will appear within the menu presented when the user browses the list of widgets to add to their home screen, as follows:<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdP7qG_e8vmD013xJKdtJ77mEUP6ehN3XPPI-gxWMmXpYGipvi0EceNgD6-kRJIKMRGYNkaC33bOLSABsMdgJBd21zICbc3dU36pNPDnOlA67gm1Gr2-5gWEX7wpegtemYoW2ad2VgvI6P/s1600/widget_menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdP7qG_e8vmD013xJKdtJ77mEUP6ehN3XPPI-gxWMmXpYGipvi0EceNgD6-kRJIKMRGYNkaC33bOLSABsMdgJBd21zICbc3dU36pNPDnOlA67gm1Gr2-5gWEX7wpegtemYoW2ad2VgvI6P/s400/widget_menu.png" width="268" /></a></div><br/>
You can alter the name that appears for your app by editing the "res/values/strings.xml" file, in the entry for "app_name".
<br /><br/>
Let's create the widget background image drawable. Right-click on the drawables folder, choose New, File, enter "batt_bg.xml" and click Finish. Enter the following code:
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#99000000"></solid>
<corners android:radius="6dp"></corners>
<size android:height="72dp" android:width="72dp"></size>
</shape>
</pre>
In this case we define the image as a rectangle Shape Drawable with a solid but semi-transparent black color filling it (using the Hex representation #ARGB). We also define the rectangle corners so that they appear rounded with the specified radius, as well as defining the image dimensions within the size element. If you look back at the widget layout XML, you will see that this image is specified as the background for the Linear Layout, which represents the entire visible widget.
<br />
<br />
Next let's add the line image to appear between the text and graphic representation of the battery level. Add another file to your drawables folder(s) by right-clicking, choosing New, File, entering "top_line.xml" and clicking Finish. Notice that we used "top_line" in the XML layout file to indicate the drawable resource within an Image View item. Add the following code to your new drawable file:
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#CCCCCCCC"></solid>
<size android:height="1dp" android:width="68dp"></size>
</shape>
</pre>
As with the background image, we define the line as a solid rectangle shape with a semi-transparent solid color, gray in this case. Again, we use the size element to specify dimensions.
<br />
<br />
Now we'll create drawable resources for our battery level bars. There are going to be six in total: one each for three colors representing low, mid and high level charge, plus a semi-transparent version of each of these three to represent mid-levels. Create six new files in your drawables folder(s), right-clicking, choosing File, New and entering the following six file names in turn: "level_shape_low.xml", "level_shape_mid.xml", "level_shape_high.xml", "level_shape_low_alpha.xml", "level_shape_mid_alpha.xml" and "level_shape_high_alpha.xml". The code within these six files will be similar - start with "level_shape_low.xml" as follows:
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_red" android:endcolor="@color/dark_red" android:startcolor="@color/dark_red"></gradient>
<size android:height="5dp" android:width="64dp"></size>
<stroke android:color="#00000000" android:width="1dp"></stroke>
</shape>
</pre>
Again, this is a rectangle Shape Drawable, with a gradient of color in which we list color resources we have not yet created. The shape defines its dimensions in the size element and a stroke, which is actually transparent, to create the illusion of empty space around the level bar. The rest of the level shapes are similar, so add the code for each as follows. For "level_shape_mid.xml":
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_yellow" android:endcolor="@color/dark_yellow" android:startcolor="@color/dark_yellow"></gradient>
<size android:height="5dp" android:width="64dp"></size>
<stroke android:color="#00000000" android:width="1dp"></stroke>
</shape>
</pre>
For "level_shape_high.xml":
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_green" android:endcolor="@color/dark_green" android:startcolor="@color/dark_green"></gradient>
<size android:height="5dp" android:width="64dp"></size>
<stroke android:color="#00000000" android:width="1dp"></stroke>
</shape>
</pre>
For "level_shape_low_alpha.xml":
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_red_alpha" android:endcolor="@color/dark_red_alpha" android:startcolor="@color/dark_red_alpha"></gradient>
<size android:height="5dp" android:width="64dp"></size>
<stroke android:color="#00000000" android:width="1dp"></stroke>
</shape>
</pre>
For "level_shape_mid_alpha.xml":
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_yellow_alpha" android:endcolor="@color/dark_yellow_alpha" android:startcolor="@color/dark_yellow_alpha"></gradient>
<size android:height="5dp" android:width="64dp"></size>
<stroke android:color="#00000000" android:width="1dp"></stroke>
</shape>
</pre>
And finally, for "level_shape_high_alpha.xml":
<br />
<pre class="xml" name="code"><shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:centercolor="@color/light_green_alpha" android:endcolor="@color/dark_green_alpha" android:startcolor="@color/dark_green_alpha"></gradient>
<size android:height="5dp" android:width="64dp"></size>
<stroke android:color="#00000000" android:width="1dp"></stroke>
</shape>
</pre>
<h3>
Step 6: Define the Widget Colors</h3><br/>
Rather than re-using the same color codes through the design code for an app, you can define them as color resources, then use them from anywhere else in the application code. This means if you decide to change your color scheme, you only have to do it in one place. As you have seen, we have been referring to color resources by name within the drawable files for the widget app, so we now need to create definitions for those colors. In your project "res/values" folder, create a new file by right-clicking the folder, choosing New, File, entering "colors.xml" and clicking Finish.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjblPTtVsIksgGAosNUrx7iF0IRg6apgm_vrJG7MBvePwF_GsaIsvmad5IbVvOkdc5BtRzlBFpYPpXmq59teINP_tW3UfDmUbrwHMfoA1LZWl9Tbpyvuf9X5bWgzm0SST51yfwWsfratT9T/s1600/color_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjblPTtVsIksgGAosNUrx7iF0IRg6apgm_vrJG7MBvePwF_GsaIsvmad5IbVvOkdc5BtRzlBFpYPpXmq59teINP_tW3UfDmUbrwHMfoA1LZWl9Tbpyvuf9X5bWgzm0SST51yfwWsfratT9T/s400/color_file.png" width="347" /></a></div>
<br />
To edit the file as XML, choose the "colors.xml" tab at the bottom of the editor pane. Enter the following code:
<br />
<pre class="xml" name="code"><resources>
<color name="dark_green">#003300</color>
<color name="light_green">#99FF66</color>
<color name="dark_red">#990000</color>
<color name="light_red">#FF9999</color>
<color name="dark_yellow">#CC3300</color>
<color name="light_yellow">#FFFF66</color>
<color name="dark_green_alpha">#99003300</color>
<color name="light_green_alpha">#9999FF66</color>
<color name="dark_red_alpha">#99FF0000</color>
<color name="light_red_alpha">#99FF9999</color>
<color name="dark_yellow_alpha">#99CC9900</color>
<color name="light_yellow_alpha">#99FFFF66</color>
</resources>
</pre>
As you can see, this defines all of the colors we referred to by name in our level Shape Drawable files. There are 12 colors in total, representing two each for the three level types plus the alpha versions of these. Notice that the only difference between a color and its alpha counterpart is the extra two HEX digits representing the transparency level.
<br />
<br />
At this point you should see all of the errors your IDE is displaying disappear, as we have provided all of the resources referred to. All of this may seem like preparation for the main event, which is implementing the Java code to update the widget. However, preparing your application resources is often one of the most time-consuming phases of an Android project - we are actually not too far away from being finished.
<br /><br/>
<h3>
Step 7: Implement a Java Class to Handle Widget Updates</h3><br/>
To create our widget app, we only have one more file to create. However, it does contain a few complex features we will take the time to go over in detail, so that you learn skills you will be able to re-use in future projects.
<br />
<br />
Create a new Java class in your project. Select your application package in the Package Explorer, which you should see inside the "src" folder. Choose File, New, Class then enter a name for your class, making sure it matches the name you entered in your Manifest file within the receiver element, "LovelyBatteryWidget" if you used the sample code above. Click Finish to see your new Java class file appear inside the package and open in the code editor.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEginDueY7Y5HKQTrOXpKSIFCz2o9mYBhLypJVBgvJgS0IdpqxKtzCDD00VEx-fII3OJsjPf2hiP-e2f-Esblp2f40MnQGm-vwHmWHzIzPSkL56vNuNMzN5ek79VUIr5GGj9Fc-Tfrsb8Jj3/s1600/java_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEginDueY7Y5HKQTrOXpKSIFCz2o9mYBhLypJVBgvJgS0IdpqxKtzCDD00VEx-fII3OJsjPf2hiP-e2f-Esblp2f40MnQGm-vwHmWHzIzPSkL56vNuNMzN5ek79VUIr5GGj9Fc-Tfrsb8Jj3/s400/java_file.png" width="336" /></a></div>
<br />
To function as a widget that will update its appearance with the battery level, your class must be structured in a particular way. Firstly, it must extend the class AppWidgetProvider, so alter your class declaration opening line as follows:
<br />
<pre class="java" name="code"> public class LovelyBatteryWidget extends AppWidgetProvider
</pre>
If you are unfamiliar with inheritance or Object Orientation it's worth reading up on the basics at least. In essence, when a class extends another class, it inherits the methods in that class. By extending the App Widget Provider class, our app does not have to provide all of the implementation details for a widget, as the superclass (the parent class we are extending) handles that for us.
<br />
<br />
Your IDE will display errors because you have not imported the required language resources. Add the following import statement above the class declaration but below the package name:
<br />
<pre class="java" name="code"> import android.appwidget.AppWidgetProvider;
</pre>
Your class file should now look similar to this:
<br />
<pre class="java" name="code">package com.yourdomain.battery;
import android.appwidget.AppWidgetProvider;
public class LovelyBatteryWidget extends AppWidgetProvider {
//main code here
}
</pre>
The content of the class will mainly be added between the opening and closing class brackets, with import statements included above. In some cases your IDE may add the import statements automatically. Add the following inside the body of the class (between the brackets):
<br />
<pre class="java" name="code">//constant to store battery steps
private final int BATTERY_STEPS = 10;
//remote views object to access visible interface elements
private RemoteViews widgetViews =
new RemoteViews("com.yourdomain.battery",
R.layout.battery_widget);
</pre>
These are instance variables, which means that they are accessible throughout the class. The first variable is a constant to store the number of battery levels we are using. The second variable gets a reference to the Remote Views for the widget, which will allow us to access the visible user interface elements in order to update them. Notice that the code contains the package name and a reference to the XML layout. You will also need the following import statement, added after the package declaration at the top of the file:
<br />
<pre class="java" name="code"> import android.widget.RemoteViews;
</pre>
Next add the "onUpdate" method:
<br />
<pre class="java" name="code">/*
* Determine what happens when the widget updates
* - this method is called repeatedly
* - frequency determined by updatePeriodMillis
* in res/xml widget info file
*/
public void onUpdate(Context context,
AppWidgetManager appWidgetManager,
int[] appWidgetIds)
{
//register for the receiver when the battery changes
Intent received =
context.getApplicationContext().registerReceiver
(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
//find out what action has been received
String receivedAction = received.getAction();
//only carry out amendments if the action is
//a change in the battery level
if (receivedAction.equals(Intent.ACTION_BATTERY_CHANGED))
{
//get the level amount, pass default value
int level = received.getIntExtra("level", 0);
//indicate the level amount within the text view
this.widgetViews.setTextViewText
(R.id.text_level, level+"%");
//call helper to show the level bars
showBars(level);
//get component to update
ComponentName appComponent =
new ComponentName(context, LovelyBatteryWidget.class);
//update the widget
AppWidgetManager.getInstance(context).updateAppWidget
(appComponent, this.widgetViews);
}
}
</pre>
The system will call this method at the interval you indicated in your XML metadata file using milliseconds. The method receives particular items of data, including the application Context, a reference to the App Widget Manager and an array of app widgets, which we don't need in this case. The Context allows us to instruct the widget to respond to receipt of information about changes in the battery level, while the App Widget Manager allows us to call the update. By supplying the "onUpdate" method, you are overriding the method in the parent class (or superclass) you are extending in this class. This just means that you are providing your own implementation of the method rather than using the one in the superclass.
<br />
<br />
Let's go over what's happening here. First, the method registers to receive the system broadcast indicating the battery level, using the passed context. <i>Note: The battery level broadcast is what's known as a "sticky" broadcast, meaning that the system allows you to access details of the last broadcast of the battery level that occurred.</i> The code then checks the received data from the broadcast receiver Intent to make sure it is an indicator of the battery level. If it is, the code gets the level, displays it within the layout text-field, then calls a helper method to update the visual indicator we created using our drawables - we will create this helper method next. Finally, the method uses the context and App Widget Manager to update the widget appearance.
<br />
<br />
Notice the line on which we display the battery level textually. The code uses the Remote Views object instance variable to gain access to the Text View item, by specifying its ID attribute. If you look at the XML layout file for the widget ("res/layout/battery_widget.xml") you will see the ID attribute within the Text View item. This code passes the desired text to display within the Text View, which includes the level as an integer followed by a percent sign.
<br />
<br />
<b>A note on receivers:</b> <i>in this section we are registering for a receiver from a receiver, since "AppWidgetProvider" is a subclass of "BroadcastRecevier". It is not normally recommended to register for one receiver inside another, as this can have unpredictable results. We get around it here by using the context to register the receiver, passing a null parameter instead of a reference to a Broadcast Receiver object, then accessing the result directly from the returned Intent object, which we are able to do because the broadcast is a "sticky" one as mentioned above. Don't worry if this seems baffling, it's just a little bit of knowledge that you may find useful in future projects.</i>
<br />
<br />
For this section of code, you need a few more import statements:
<br />
<pre class="java" name="code">import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
</pre>
After the closing bracket for your "onUpdate" method add the "showBars" method to display a visual indicator of the battery level:
<br />
<pre class="java" name="code">/*
* Helper method to show levels using bar images
* - takes the last read battery level as parameter
*/
private void showBars(int currLevel)
{
/*
* Set the drawable images and visibility
* depending on the current level
*
* Algorithm: For each of the ten levels,
* if the battery is at that level or above,
* set the correct graphic and visibility.
* If not set the image invisible.
* E.G. for 76% seven bars should be displayed fully,
* from the bottom up
*/
}
</pre>
This is just the outline of the method, we will add more code inside it. If you are new to creating your own custom Java methods, notice that the method name matches the method called from the last section of code, and that the parameter type is the same as what we passed to the method, which is an integer. The method receives the integer parameter as an indicator of the battery level to display. We need to determine which level bar images should be displayed, depending on the current level of the battery. Add the following chained conditional tests inside the method:
<br />
<pre class="java" name="code">if(currLevel>=10)
{
this.widgetViews.setImageViewResource(R.id.bar1,
R.drawable.level_shape_low);
this.widgetViews.setViewVisibility(R.id.bar1, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar1, View.INVISIBLE);
if(currLevel>=20)
{
this.widgetViews.setImageViewResource(R.id.bar2,
R.drawable.level_shape_low);
this.widgetViews.setViewVisibility(R.id.bar2, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar2, View.INVISIBLE);
if(currLevel>=30)
{
this.widgetViews.setImageViewResource(R.id.bar3,
R.drawable.level_shape_low);
this.widgetViews.setViewVisibility(R.id.bar3, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar3, View.INVISIBLE);
if(currLevel>=40)
{
this.widgetViews.setImageViewResource(R.id.bar4,
R.drawable.level_shape_mid);
this.widgetViews.setViewVisibility(R.id.bar4, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar4, View.INVISIBLE);
if(currLevel>=50)
{
this.widgetViews.setImageViewResource(R.id.bar5,
R.drawable.level_shape_mid);
this.widgetViews.setViewVisibility(R.id.bar5, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar5, View.INVISIBLE);
if(currLevel>=60)
{
this.widgetViews.setImageViewResource(R.id.bar6,
R.drawable.level_shape_mid);
this.widgetViews.setViewVisibility(R.id.bar6, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar6, View.INVISIBLE);
if(currLevel>=70)
{
this.widgetViews.setImageViewResource(R.id.bar7,
R.drawable.level_shape_high);
this.widgetViews.setViewVisibility(R.id.bar7, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar7, View.INVISIBLE);
if(currLevel>=80)
{
this.widgetViews.setImageViewResource(R.id.bar8,
R.drawable.level_shape_high);
this.widgetViews.setViewVisibility(R.id.bar8, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar8, View.INVISIBLE);
if(currLevel>=90)
{
this.widgetViews.setImageViewResource(R.id.bar9,
R.drawable.level_shape_high);
this.widgetViews.setViewVisibility(R.id.bar9, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar9, View.INVISIBLE);
if(currLevel>=100)
{
this.widgetViews.setImageViewResource(R.id.bar10,
R.drawable.level_shape_high);
this.widgetViews.setViewVisibility(R.id.bar10, View.VISIBLE);
}
else
this.widgetViews.setViewVisibility(R.id.bar10, View.INVISIBLE);
</pre>
Try not to be intimidated by the length of this section, if you look through it you'll see it's fairly simple. For each of the ten levels (0-10, 10-20 and so on) the code checks whether the battery is at that level or above. If it is, the code sets the fully solid image for that level and instructs the system that it should be visible. If not, it sets the level View invisible. Each level is referred to using the ID attribute for its corresponding Image View item in the layout XML. <i>In another context, it would be more efficient to use a loop structure to carry out this process, but here we need to use the auto-generated "R" data to access the View items, so that is not possible, hence the lengthy conditional.</i>
<br />
<br />
Next we need to deal with partial levels. For example, if the level is 35%, we want to display three full bars and one partial bar, indicating that the level is between 30 and 40. Add the following:
<br />
<pre class="java" name="code">/*
* We also want to show a partially visible level to
* represent the battery level more accurately.
* E.G. for 34% there should be three fully visible
* bars and one partially visible. We need to work out
* which level should be set partially visible
*/
//deal with the remainder
int partLevel = currLevel%BATTERY_STEPS;
//find out how many full levels we have
int fullSteps = currLevel-partLevel;
//find out which is the next level up and
//call helper method to set partially visible
if(partLevel>0) setPartStep((fullSteps/BATTERY_STEPS)+1);
</pre>
This code first determines the remainder of the level after dividing by ten, then calculates how many full levels we have. Finally, if the remainder is greater than zero (e.g. the level is 34 or 79 rather than 30 or 70), the code calls a helper method, passing the number of the step we want to partially display. Next we will write the helper method. After the closing bracket for the "showBars" method but before the closing bracket for the class as a whole, add the following method outline:
<br />
<pre class="java" name="code">/*
* Helper method to set partial level step drawable
* - takes the partial level to set visible
*/
private void setPartStep(int partLevel)
{
//method implementation
}
</pre>
This is the method outline, matching the name we called in the last section of code and taking an integer parameter, which is what we passed from there. Add the following code (between the method brackets):
<br />
<pre class="java" name="code">//precaution - should not really be necessary
if(partLevel>BATTERY_STEPS) return;
else
{
//the process should only be setting one level
//I.E. for 45% the fifth bar up from the bottom
//should be set partially visible
//- find out which level and set the image drawable,
//then visibility
switch(partLevel)
{
case 1:
this.widgetViews.setImageViewResource(R.id.bar1,
R.drawable.level_shape_low_alpha);
this.widgetViews.setViewVisibility(R.id.bar1,
View.VISIBLE);
break;
case 2:
this.widgetViews.setImageViewResource(R.id.bar2,
R.drawable.level_shape_low_alpha);
this.widgetViews.setViewVisibility(R.id.bar2,
View.VISIBLE);
break;
case 3:
this.widgetViews.setImageViewResource(R.id.bar3,
R.drawable.level_shape_low_alpha);
this.widgetViews.setViewVisibility(R.id.bar3,
View.VISIBLE);
break;
case 4:
this.widgetViews.setImageViewResource(R.id.bar4,
R.drawable.level_shape_mid_alpha);
this.widgetViews.setViewVisibility(R.id.bar4,
View.VISIBLE);
break;
case 5:
this.widgetViews.setImageViewResource(R.id.bar5,
R.drawable.level_shape_mid_alpha);
this.widgetViews.setViewVisibility(R.id.bar5,
View.VISIBLE);
break;
case 6:
this.widgetViews.setImageViewResource(R.id.bar6,
R.drawable.level_shape_mid_alpha);
this.widgetViews.setViewVisibility(R.id.bar6,
View.VISIBLE);
break;
case 7:
this.widgetViews.setImageViewResource(R.id.bar7,
R.drawable.level_shape_high_alpha);
this.widgetViews.setViewVisibility(R.id.bar7,
View.VISIBLE);
break;
case 8:
this.widgetViews.setImageViewResource(R.id.bar8,
R.drawable.level_shape_high_alpha);
this.widgetViews.setViewVisibility(R.id.bar8,
View.VISIBLE);
break;
case 9:
this.widgetViews.setImageViewResource(R.id.bar9,
R.drawable.level_shape_high_alpha);
this.widgetViews.setViewVisibility(R.id.bar9,
View.VISIBLE);
break;
case 10:
this.widgetViews.setImageViewResource(R.id.bar10,
R.drawable.level_shape_high_alpha);
this.widgetViews.setViewVisibility(R.id.bar10,
View.VISIBLE);
break;
default:
break;
}
}
</pre>
We use a switch/ case statement here because we only need to set one level partially visible. The switch statement tests which level is to be set. When it hits on the correct one, it specifies the partially transparent image for that level, then sets it to be visible, before breaking out of the statement.
<br />
<br />
We need one more import statement at the top of the class file:
<br />
<pre class="java" name="code"> import android.view.View;
</pre>
And that's it! Test your app by launching an AVD and running your widget app on it. When you run a widget app in the emulator, Eclipse (or your chosen IDE) may display error messages informing you that the app cannot be launched, but don't worry. Once you have installed the widget app on a virtual device, add it as you would on an actual device, by long-pressing the homescreen, selecting "Widget" and browsing through the list until you find yours. Once you have it on the homescreen it will keep appearing each time you launch that virtual device.
<br />
<br />
When you run the widget app on an AVD device, it will display at 50% by default. To see it working properly, export the app and install it on an actual Android device. Here is a sample of the widget at three different levels, running on an actual device.<br /><br/>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2eCudqUiaauF6L8j-TPndV0airnh8hDdWGhTBYqx3czKEazSnWHeCnCrf-1baKDWrgWUxHC_VIwjwKfpaRcwLqI4n6fb7glHcOcHyTFk8NRxyKV73ynQ2RdssfqqssT70ZhcIn15B51QX/s1600/level75perc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2eCudqUiaauF6L8j-TPndV0airnh8hDdWGhTBYqx3czKEazSnWHeCnCrf-1baKDWrgWUxHC_VIwjwKfpaRcwLqI4n6fb7glHcOcHyTFk8NRxyKV73ynQ2RdssfqqssT70ZhcIn15B51QX/s1600/level75perc.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9UEN7ufkZneg8oKf6trwIt8sa6W_wwq43wnZFd0fPNN4vdUlmBNSB9BJRJ_2Aqa96LTCx2U11SuH6Yl7cIdJFHN-6GQ3NsPExZiUgdF-S7I0vgT4cMLIFF4DMueWYiL4B776TC1zydRkq/s1600/level48perc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9UEN7ufkZneg8oKf6trwIt8sa6W_wwq43wnZFd0fPNN4vdUlmBNSB9BJRJ_2Aqa96LTCx2U11SuH6Yl7cIdJFHN-6GQ3NsPExZiUgdF-S7I0vgT4cMLIFF4DMueWYiL4B776TC1zydRkq/s1600/level48perc.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUrTXS3kC_z9deCgEPbeN58i5JZo6lzb5gGaGvHcoEA1Afv5o7ke6i3zisn-kodvaZYYS3q_vYCVjW8iUc33L_mxDh1YGQbpaHq3R4giZATqdWZHpVQxsiN9H9vD562kRolIaurYhQzgy7/s1600/level100perc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUrTXS3kC_z9deCgEPbeN58i5JZo6lzb5gGaGvHcoEA1Afv5o7ke6i3zisn-kodvaZYYS3q_vYCVjW8iUc33L_mxDh1YGQbpaHq3R4giZATqdWZHpVQxsiN9H9vD562kRolIaurYhQzgy7/s1600/level100perc.png" /></a></div>
<br />
<h3>
Notes</h3><br/>
As mentioned above, you may wish to tailor your widget appearance to different device sizes, depending on your own particular design. If you target SDK version 14, your widgets will automatically be displayed with margins around them, so bear this in mind. If you want to explore this topic to a more advanced level, there are a number of possible areas to consider, such as making the widget occupy more than one cell. Our widget at the moment can only update a maximum of every 30 minutes - if you want to create one that can update more often, you can also look into using the Alarm Manager in conjunction with a Service or Activity class. You can make the widget interactive, by detecting user clicks, for example to allow the user to choose settings such as update frequency. You can also include a configuration Activity class/ Intent in your widget app, to set advanced config details that cannot be set using the XML info file we created for this tutorial.
<br />
<br />
The <a href="http://benormal.info/Android_Battery_Widget_Source_Files.zip">source code files</a> contain everything in this tutorial plus some additional notes. To find out more about the topics in this tutorial or to have a go at some of the more advanced topics, see the following sections of the official Android Developer Guide:
<br />
<ul>
<li>
<a href="http://developer.android.com/guide/topics/appwidgets/index.html" target="_blank" title="App Widgets">App Widgets</a>
</li>
<li>
<a href="http://developer.android.com/guide/practices/ui_guidelines/widget_design.html" target="_blank" title="App Widget Design Guidelines">App Widget Design Guidelines</a>
</li>
<li>
<a href="http://developer.android.com/training/monitoring-device-state/battery-monitoring.html" target="_blank" title="Monitoring the Battery Level and Charging State">Monitoring the Battery Level and Charging State</a>
</li>
<li>
<a href="http://developer.android.com/guide/topics/graphics/2d-graphics.html" target="_blank" title="Canvas and Drawables">Canvas and Drawables</a>
</li>
<li>
<a href="http://developer.android.com/guide/topics/ui/layout-objects.html" target="_blank" title="Common Layout Objects">Common Layout Objects</a>
</li>
<li>
<a href="http://developer.android.com/guide/topics/ui/declaring-layout.html" target="_blank" title="XML Layouts">XML Layouts</a>
</li>
<li>
<a href="http://developer.android.com/guide/topics/resources" target="_blank" title="Application Resources">Application Resources</a>
</li>
</ul>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com1tag:blogger.com,1999:blog-8119365238245677514.post-21239574049061444562012-10-14T18:43:00.001+01:002012-10-14T18:43:46.429+01:00Detecting and Handling Button Clicks on AndroidIn Android apps, there are two common ways to detect and handle user clicks on UI elements such as buttons: by attaching a listener to a layout item in Java or by including an <i>onClick</i> attribute in the item's layout XML code. Either way, you will typically include the Java code to execute on clicks inside the Activity class hosting the layout with the clickable item in it.
<br />
<br />
Here's an overview of each approach:
<br />
<br />
<b>Attaching the Listener in Java</b>
<br />
<br />
Include the button in an XML layout file, assigning it an ID attribute so that you can identify it in the Java Activity code:
<br/>
<pre class="xml" name="code">
<Button
android:id="@+id/your_button_id"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/your_button_label"
/>
</pre>
<br/>
The text attribute should be a string included in your <em>res/values/strings.xml</em> file with the specified name:
<br/>
<pre class="xml" name="code">
<string name="your_button_label">Click Me</string>
</pre>
<br/>
In the Activity using the layout, applied as follows...
<br/>
<pre class="java" name="code">
setContentView(R.layout.layout_file_name);
</pre>
<br/>
...extend the class to implement the click listener interface:
<br/>
<pre class="java" name="code">
public class YourActivity extends Activity implements OnClickListener
</pre>
<br/>
In your <em>onCreate</em> method, find a reference to the button and attach a click listener to it:
<br/>
<pre class="java" name="code">
Button yourBtn = (Button)findViewById(R.id.your_button_id);
yourBtn.setOnClickListener(this);
</pre>
<br/>
Add the <em>onClick</em> method to the class:
<br/>
<pre class="java" name="code">
public void onClick(View v) {
}
</pre>
<br/>
Inside the method, find out whether your button has been clicked:
<br/>
<pre class="java" name="code">
if (v.getId()==R.id.your_button_id) {
}
</pre>
<br/>
Inside the conditional block, you can add whatever code you want to execute when users click the button.
<br/><br/>
<b>Using the <i>onClick</i> Attribute</b>
<br />
<br />
Using the <em>onClick</em> attribute is typically a little simpler, although there are some cases in which it isn't possible, for example where UI items are being created programmatically in Java rather than in XML layout files.
<br/><br/>
To use this approach, include your button in an XML layout file with one additional line:
<br/>
<pre class="xml" name="code">
<Button
android:id="@+id/your_button_id"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/your_button_label"
android:onClick="buttonClicked"
/>
</pre>
<br/>
The <em>onClick</em> method should include the name of the method you want to execute when users click the button. In the Activity class, the layout is set as the content view using the same technique as the first approach. When you use the <em>onClick</em> attribute there is no need to implement the click listener interface, to retrieve a reference to the button or to attach an event listener to it. Instead of providing the <em>onClick</em> method, include the method listed as your XML attribute in the Activity class hosting the layout with the button in it:
<br/>
<pre class="java" name="code">
public void buttonClicked(View view){
}
</pre>
<br/>
The method name must match what you included in your XML attribute. Whatever method you list as an <em>onClick</em> attribute will receive a view parameter representing the UI item clicked. This allows you to use the same method to handle clicks on more than one item, just check which one has been clicked using the passed view parameter. Inside the method, include whatever code you want to execute when users click the button.
<br/><br/>
The <em>onClick</em> attribute is available on devices running Android API 4.0 and up.Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-90860782283067305272012-10-09T10:28:00.001+01:002012-10-14T17:35:59.788+01:00Developing Android Clock WidgetsI recently created a tutorial series for Mobiletuts+ on <a href="http://mobile.tutsplus.com/tutorials/android/building-a-customizable-android-analog-clock-widget-tuts-premium/">creating an Android clock widget</a>. It was the first time I had attempted the task, so I thought I'd share a couple of the things I discovered.<br />
<br />
<b>Analog or Digital</b> <br />
<br />
First, the process for creating analog and digital clocks is totally different. For an analog clock widget, the process is pretty straightforward, in fact the most time consuming part is probably creating your clock design. The basic tasks in creating a simple analog clock widget are as follows:<br />
<br />
<ul>
<li>Create a widget project, setup the properties in the Manifest and XML resource file.</li>
<li>Create images for the dial, minute and hour hands for each density.</li>
<li>Add an AnalogClock element to your layout file.</li>
<li>Extend AppWidgetProvider and receive updates.</li>
</ul>
<br />
For a digital clock widget, more programming is involved. There is a DigitalClock class/ View, but unlike the AnalogClock, the DigitalClock cannot be used within the layout for a widget, only within standard apps. This means that you need to implement the details yourself, for example using a Service or AlarmManager for updating the widget appearance - there are potentially serious performance issues.<br />
<br />
<b>XML Layout</b><br />
<br />
The following code outlines including an AnalogClock element within your widget layout file:<br />
<pre class="xml" name="code">
<AnalogClock
android:id="@+id/AnalogClockID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:dial="@drawable/your_dial_image"
android:hand_hour="@drawable/your_hour_hand_image"
android:hand_minute="@drawable/your_minute_hand_image"
/>
</pre>
Just replace the dial, minute and hour hand references with the names of your own drawable image files. The minute and hour hands should be included as though pointing at 12 o'clock, with the hands placed centrally horizontally within the dial image.
<br /><br />
<b>Clicks</b><br />
<br />
If you do develop an Android clock widget, you need to decide what will happen on user clicks. Users have now come to expect certain behaviour as standard on clicking clock widgets, such as launching the device alarm clock (although there is as yet no standard way of doing this). Another option is to allow the user to configure the clock, choosing between designs - this is what I did in the tutorial series.<br />
<br />
<b>Launcher</b><br />
<br />
Although widgets are of course accessed from the device homescreen, there is invariably the issue of users attempting to launch a widget app from the device menu. To accommodate this, you can add a launcher Activity to your widget app, which contains instructions on how to add the widget.<br />
<br />
<b>Conclusion</b><br />
<br />
If you haven't attempted any Android widgets yet, don't be afraid to have a go, they are generally not too tough to implement. For clock widgets, it's easy enough as long as you go for analog, a little trickier for digital.<br />
<br />
<b>Related Info</b><br />
<br />
<ul>
<li><a href="http://developer.android.com/reference/android/widget/AnalogClock.html">Android AnalogClock class</a></li>
<li><a href="http://developer.android.com/reference/android/widget/DigitalClock.html">Android DigitalClock class</a></li>
<li><a href="http://developer.android.com/guide/topics/appwidgets/index.html">Developer Guide: App Widgets</a></li>
<li><a href="http://developer.android.com/guide/practices/ui_guidelines/widget_design.html">App Widget Design Guidelines</a></li>
<li><a href="http://www.vogella.com/articles/AndroidWidgets/article.html">Vogella on Android Widgets</a></li>
<li><a href="http://www.droiddraw.org/widgetguide.html">DroidDraw: Visual Guide to Android GUI Widgets</a></li>
</ul>
<br />Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com1tag:blogger.com,1999:blog-8119365238245677514.post-1683469396543900492012-10-01T11:11:00.001+01:002012-10-01T11:11:43.622+01:00Google's Project GlassWhen Project Glass hit the headlines earlier this year following Sergey Brin's demo at Google I/O I must admit I wasn't massively interested. I've never thought much about Augmented Reality/ wearable computing other than finding the concept vaguely scary.
<br/><br/>
However, following the London Olympics/ Paralympics I found myself thinking about the role of technology in sport. It looks as though sport is going to be one of the main areas developers will look to target with Project Glass apps - there are already projects under development to that end.
<br/><br/>
Although I'm not competitive, I love to swim and started to think about the possibility of smart swimming goggles. Since Project Glass runs Android, I thought about how I would love to come up with some swimming apps. I'm a big fan of swimming techniques including the Shaw Method and Total Immersion, so initial app ideas would probably focus on the quality of the swimming experience rather than exclusively on competitive/ high performance aspects. Following a cursory Google search on the topic, I was pleased to find that the company has indeed acquired a patent for swimming goggles.
<br/><br/>
Anyway, this development has basically got me excited about programming for the first time in a while. Although I love developing applications, I haven't felt too creatively stimulated recently, mainly because I don't spend enough time working on my own projects. I've got a lot to learn if I do want to target these devices, as I know virtually nothing about AR or wearable computing at the moment. I'll be posting on the topic as I learn more about it, and keep my fingers crossed that the smart goggles do become a reality.
<br/><br/>
Here are some related links:
<br/><br/>
<a href="http://www.drdobbs.com/tools/hacking-for-fun-programming-a-wearable-a/240007471">Hacking for Fun: Programming a Wearable Android Device</a><br/>
<a href="http://mashable.com/2012/06/27/google-glass-pro-sports/">Could Google Glass Change Pro Sports Forever?</a><br/>
<a href="http://dailynews.openwaterswimming.com/2012/07/google-googles-for-open-water.html">Google Googles For The Open Water?</a><br/>
<a href="http://www.seobythesea.com/2011/04/google-acquires-swimming-goggle-patent/">Google Acquires Swimming Goggle Patent</a><br/>
<a href="http://en.wikipedia.org/wiki/Project_Glass">Wikipedia: Project Glass</a><br/>
<a href="https://plus.google.com/+projectglass/posts">Project Glass on Google+</a>
<br/><br/>
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/D7TB8b2t3QE" width="560"></iframe>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-51633404948002211812012-08-02T17:42:00.000+01:002012-08-02T17:42:10.157+01:00Using the Android Crop Intent and ActionRecently I discovered that using standard intents and actions to capture and crop an image was not as straightforward as I had expected. I had assumed there would be a standard, reliable way to launch any apps that can perform a cropping action on images but was unfortunately wrong. Launching the camera is pretty consistent, but cropping an image you have either allowed the user to capture with the camera or choose from the device, for example with a file explorer app or the standard gallery app, is not so easy.<br />
<br />
There is a generic action you can use for cropping that is supported on many user devices, but not all of them. The following represents the closest we have to a standard approach to launching a cropping Activity:<br />
<br />
<pre class="java" name="code">Intent croppingIntent =
new Intent("com.android.camera.action.CROP");
</pre><br />
You need to pass various additional data values to the Intent before starting it, and if you want the cropped image to return to your code you need to call the Intent using startActivityForResult, then implement onActivityResult to process the returned cropped image.<br />
<br />
So far so good, but unfortunately there are lots of Android vendors whose devices do not support this action. You have two broad options: <br />
<br />
<ul><li>Only provide your cropping functionality to users whose devices support this Intent</li>
<li>Query the user device in order to target specific cropping Activities</li>
</ul><br />
If you opt for the first approach, you can include the code in which you call the Intent in a try block, with a catch block outputting an informative error message letting the user know why they can't complete the cropping action. If you opt for the second approach, you have a more complex task in front of you.<br />
<br />
See this Stack Overflow post for an example of how to handle differing device crop Activities:<br />
<a href="http://stackoverflow.com/questions/8585341/android-camera-intent-with-crop">Android Camera Intent with Crop</a><br />
<br />
For an overview of using the basic crop action above, see my tutorial on Mobiletuts+ for more details:<br />
<a href="http://mobile.tutsplus.com/tutorials/android/capture-and-crop-an-image-with-the-device-camera/">Capture and Crop an Image with the Device Camera</a><br />
<br />
It seems the Android system is plagued a little by this type of issue. When approaching another task recently I found there is a similar problem when attempting to launch the alarm clock app on a user device - a common aim, particularly for clock widget apps.Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com1tag:blogger.com,1999:blog-8119365238245677514.post-52281371267445455772012-02-20T18:22:00.004+00:002013-03-06T20:38:55.076+00:00Creating an Android Battery Widget<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihSmLxp4bD_yVqo6nHOj4z8bujh5oyVT_dhK8cdnPfRjhQigPXLMMqoGW0y0wA30HjLCAx7xCILG0_7DanFh1F3ZQkKaAYagK8LduGbm18Eq_TMEf6l-KoveSNBHwJ4OFgrwdBulo3r3hq/s1600/battery_preview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihSmLxp4bD_yVqo6nHOj4z8bujh5oyVT_dhK8cdnPfRjhQigPXLMMqoGW0y0wA30HjLCAx7xCILG0_7DanFh1F3ZQkKaAYagK8LduGbm18Eq_TMEf6l-KoveSNBHwJ4OFgrwdBulo3r3hq/s1600/battery_preview.png" /></a></div><br />
I recently approached the task of developing an Android widget for the first time. I created an Android battery level widget, mainly so that I could write a tutorial on it.<br />
<br />
The tutorial was originally published on the Tuts+ marketplace, which has since ceased to operate. Here's a copy of it: <a href="http://androidthings.blogspot.co.uk/2013/03/jump-into-android-create-battery-level.html">Jump Into Android: Create a Battery Level Widget</a><br />
<br />
Anyway, in this article I thought I'd run through a few tips for creating Android widgets, with specific guidance on retrieving and displaying information about aspects of phone state, such as the battery level. We won't go into too much detail here, but hopefully you'll find it a useful overview of Android widget development.<br />
<br />
<br />
<b>What's the Difference?</b><br />
<br />
In many ways widget development for Android is the same as development for any other app type on the platform. However, although the differences are slight, they can throw you off when you attempt a widget for the first time. I would strongly recommend not attempting a widget as your first app, but instead trying Android widget development after you've tried developing at least one standard application.<br />
<br />
You will presumably already know the difference between widgets and other Android apps from the user's point of view, so let's start there. Widgets are not launched from the application menu, but are instead added to the user's homescreen. Some widgets are interactive, normally allowing users to choose settings on pressing the widget once it is on screen, or when it runs for the first time. The download and installation process is basically the same as for other apps.<br />
<br />
<br />
<b>What you Don't Need to Do</b><br />
<br />
Since widget apps are not launched in the same way as normal apps, your project structure does not need a main Activity class to execute when the application starts up. As well as removing the need for an Activity class file, this means you do not need to include your main launcher Activity in the project Manifest XML file.<br />
<br />
<br />
<b>What to Do Instead</b><br />
<br />
Instead of a main Activity class, your widget apps need to extend the AppWidgetProvider class. You also need to include your widget provider in the Manifest as a receiver item, specifying a metadata file along with it. If your widget is going to update, you need to indicate this within the Manifest too, using an intent filter. Your metadata file should be saved in "res/xml" and the code within it should define the basic aspects of your widget, including its dimensions and update frequency where appropriate. The metadata file can also specify an initial XML layout resource to use when the widget appears.<br />
<br />
<br />
<b>Options</b><br />
<br />
That's basically all you need for a widget, but depending on your own project you may need additional elements. For example, you can override the AppWidgetProvider methods, such as onUpdate, specifying what should happen when the widget updates, which will often involve altering the visual display.<br />
<br />
You can optionally include an Activity in your app for configuring the widget. Similarly, you can make the widget interactive by supplying a click listener and presenting an options setting section for your users.<br />
<br />
<br />
<b>Running and Testing</b><br />
<br />
Testing widgets is roughly the same as testing other Android apps, with some exceptions depending on the nature of your own particular projects. For example, when I created my battery level widget, I could only test it properly by running it on a device, because the emulator by default only shows a battery level of 50%. It's always preferable to test your apps on real devices anyway.<br />
<br />
Some widgets have serious performance implications. For example, you can use the AlarmManager class to provide more frequent updates to a widget than you can using the XML metadata method. In such apps, you really need to pay extra attention to efficiency, or your users will be dismayed to see their battery levels draining too fast.<br />
<br />
<br />
<b>Phone State Including Battery Level</b><br />
<br />
So far we've discussed widgets generally, but you have an additional set of considerations if you're creating a widget to indicate phone state such as battery level. To create this type of widget, you need to register for a receiver. This basically means telling the system to inform your app about changes in state.<br />
<br />
If you are setting your widget update frequency in the XML metadata, the most often it can receive updates is every 30 minutes. To update more often, you can use a service, implementing an alarm if the widget needs to update when the device is asleep. You will also need a service if your widget is fetching data over the Web.<br />
<br />
The Android system issues broadcasts about certain aspects of the device. Some of these are described as "sticky", including the battery level. This means that the last broadcast hangs around the system, allowing your widgets to access the data within it at any time. For a battery level widget that only updates at the frequency set in the XML metadata, this means that the displayed level will actually be whatever the last level broadcast was, which may have been any time in the past half hour at most. Naturally, this is not ideal for all apps, which is why many of them use services and alarms.<br />
<br />
<br />
<b>Conclusion</b><br />
<br />
So that's an overview of the basics when developing widget apps. Here are a few related links:<br />
<ul><li><a href="http://developer.android.com/guide/topics/appwidgets/index.html">Android Developers Guide - App Widgets</a></li>
<li><a href="http://www.vogella.de/articles/AndroidWidgets/article.html">Vogella - Android Homescreen Widgets</a></li>
<li><a href="http://buildmobile.com/how-to-code-an-android-widget">Build Mobile - How to Code an Android Widget</a></li>
<li><a href="http://developer.android.com/guide/practices/ui_guidelines/widget_design.html">Android Developers Guide - App Widget Design Guidelines</a></li>
<li><a href="http://developer.android.com/training/monitoring-device-state/battery-monitoring.html">Android Developers Guide - Monitoring the Battery Level and Charging State</a></li>
</ul>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-31541002256190256312012-01-31T22:03:00.003+00:002012-03-13T16:52:12.637+00:00Object Oriented Concepts for Android Development in Java<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJwJcqlGbKFxX5s9T5DgtlVr1GJNB5Um9NotI7REsYBxtkFUzUsenhYCPdbwpFX9VlOxrxhrPWpMmpvnX1WeD86QuSdutf4nbz37QfF0ugNmjm69u_uJK5NvtJIk7adl9ThH6UJoqia-vH/s1600/android_oo_preview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJwJcqlGbKFxX5s9T5DgtlVr1GJNB5Um9NotI7REsYBxtkFUzUsenhYCPdbwpFX9VlOxrxhrPWpMmpvnX1WeD86QuSdutf4nbz37QfF0ugNmjm69u_uJK5NvtJIk7adl9ThH6UJoqia-vH/s1600/android_oo_preview.png" /></a></div>If you're learning Android development but have no prior experience of either Java or Object Oriented development in general, you can get yourself up to speed on the essential concepts pretty easily. A few aspects of Object Oriented development can help to make the best of your Android projects, without having to embark on a lengthy training process.<br />
<br />
Providing you have programming experience of some kind, you can go some way towards getting to grips with Object Oriented Android by familiarising yourself with the basic principles we'll introduce in this article. Along the way we'll hopefully demystify some potentially confusing language you may have come across on the topic.<br />
<br />
<b>Classes and Objects</b><br />
<br />
Object Oriented development essentially means dividing up the processing tasks in an application between a group of objects. Developers begin designing such applications by defining these objects at an abstract level, assigning the various responsibilities required by the app. To implement objects in code, you create class declarations.<br />
<br />
A class declaration is normally a single file in a Java project, in which you declare the properties and behaviour that objects of the class will provide. Think of a class declaration as a description of an object in general terms. Once an app has a class declaration, other code within the application can create objects of the class, each of which will match the description outlined in the declaration, but with differences in terms of data.<br />
<br />
The following Java code demonstrates a simple class declaration for illustration:<br />
<br />
<pre class="java" name="code">public class Worker {
//instance variable
private String name;
//constructor method
public Worker(String workerName) {
name=workerName;
}
//method to return name
public String getName() { return name; }
} </pre><br />
<i><b>Using Objects</b></i><br />
<br />
Code external to the class, for example within another Java file in the application package, can instantiate objects of this class as follows:<br />
<br />
<pre class="java" name="code">Worker adminHelper = new Worker("Jim");
Worker managementHelper = new Worker("Mary");
</pre><br />
This code declares and instantiates two Worker object variables. Stating the name and type of an object is declaring it. Creating an instance of the class and assigning this to the object variable is instantiation. Although these two objects are of the same class, they have different data, in this case simply the string name variable.<br />
<br />
When this code executes, Java runs the constructor method within the class declaration. Within the constructor, the code assigns a value to the one class instance variable with the string value passed as a parameter when creating the new object. Once the "customer" code has an object of the class, it can call any public methods in it as follows:<br />
<br />
<pre class="java" name="code">String adminName = adminHelper.getName();</pre><br />
The "getName" method returns the string instance variable. Public methods and variables can be accessed outside the class, while private resources, such as the instance variable, are only available inside the declaration.<br />
<br />
These examples are for demonstration and are therefore abstract, we'll get to practical, Android-based examples next.<br />
<br />
<hr /><b>Android App Classes</b><br />
<br />
If you've already started developing Android apps you will have created classes, although some of them may have a different structure to the example above. The Android platform does certain things slightly differently to the typical Java application, but the same patterns apply.<br />
<br />
Your initial Android projects will likely have some Activity classes in them. Unlike a standard Java class, an Activity class is instantiated by the system when your code creates and starts an Intent object, rather than by using the "new" keyword as in the example above. To dictate what should happen when an Activity class is instantiated, you add code to the "onCreate" method rather than a constructor.<br />
<br />
You can create standard Java classes to handle specific processing areas within your apps, as well as using the Android classes. When your apps use classes within the Android platform, such as the Activity class, they use inheritance.<br />
<br />
<hr /><b>Inheritance</b><br />
<br />
If you have any existing Android projects in which you have Activity classes, you have already used inheritance. The class declaration for an Activity starts like this:<br />
<br />
<pre class="java" name="code">public class HelpSection extends Activity</pre><br />
The class name will vary for your own Activities. The phrase "extends Activity" means that the class is inheriting from the Android Activity class. When a Java class extends another class, it inherits the methods of that class. The parent class being extended is referred to as the superclass, with the extending class known as the subclass. The following sample code demonstrates extending the Worker class above:<br />
<br />
<pre class="java" name="code">public class Administrator extends Worker {
public Administrator(String adminName) {
super(adminName);
}
}
</pre><br />
The constructor method in the subclass calls the constructor for the superclass. This class can provide additional methods and variables that are specific to its own area of responsibility. Inheritance is essentially a way to re-use code, with extending classes able to make use of existing resources within an application or within the Java and Android platforms.<br />
<br />
By extending the Android classes, your own classes inherit their functionality, saving you from having to implement certain details. For example, the Activity superclass handles the details of presenting a user interface screen to your users.<br />
<br />
The inheritance structures you are most likely to use at first are for user interface elements, but you can extend any existing Java and Android classes you find useful. This is a key feature of Object Oriented development, and allows you to focus your energy on the aspects of your own projects that make them unique.<br />
<br />
<i><b>Overriding</b></i><br />
<br />
An inheriting class can provide a dedicated implementation of any method in the superclass it is extending. If you provide a method in a subclass that is also in the superclass, this new version of the method overrides the superclass version. If you want to carry out the same processing as the superclass method and then additional processing of your own, you can begin the method implementation by first calling the implementation in the superclass as follows:<br />
<br />
<pre class="java" name="code">public void doSomething() {
super.doSomething();
//additional processing
}
</pre><br />
<hr /><b>Interfaces</b><br />
<br />
As we have seen, with class declarations, you define the behaviour of object instances. Interfaces are another way to influence object behaviour. An interface in Java is like a contract, specifying a series of methods that implementing classes must provide.<br />
<br />
Interface declarations list method signatures, each signature including the method name plus an indication of the parameters and return type. Interfaces do not provide implementation details for the methods, so the implementing classes need to do this. In other words, an interface dictates what the class will do, and the class declaration describes how it will do it.<br />
<br />
Again, if you have already started with Android you may have implemented some interfaces. The Android platform provides a range of interfaces for delivering user interaction, such as the "OnClickListener" interface. You can indicate that a class will implement an interface using the following syntax:<br />
<br />
<pre class="java" name="code">public class HelpSection extends Activity implements OnClickListener
</pre><br />
If you are programming in an Integrated Development Environment such as Eclipse, the program will display error messages when you initially add this code. This is one of the most useful aspects of an IDE, as it reminds you to provide the interface methods, and will continue to show errors until you do.<br />
<br />
For the "OnClickListener" interface, your class must provide the "onClick" method, responding to user interaction with your Activity. Implementing an interface is therefore making a commitment that your class will exhibit certain generic behaviours. It's up to you to decide exactly how your classes implement them.<br />
<br />
<hr /><b>Developing in Eclipse</b><br />
<br />
Eclipse is designed for developing Object Oriented projects, so it has a number of features you may find useful for your Android apps. The Type Hierarchy view helps to visualise projects with reference to the concepts we've gone over here. For example, if you have a class which is extending another class, you can see its hierarchy within your application, and within the platform as a whole.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIvFKWRLPhwinbUabgKDJfl64zLvnISVVkxdUvlcMENbclYq94-hLZzuy4mk5mB7KXOOeOCL26QC55styrlyR0oODFEGMaSeLraG8KZ7t8Irmou5gK-8HWxWPNY7Kl9H0_MBJ-heVaiiV0/s1600/type_hierarchy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIvFKWRLPhwinbUabgKDJfl64zLvnISVVkxdUvlcMENbclYq94-hLZzuy4mk5mB7KXOOeOCL26QC55styrlyR0oODFEGMaSeLraG8KZ7t8Irmou5gK-8HWxWPNY7Kl9H0_MBJ-heVaiiV0/s1600/type_hierarchy.png" /></a></div><br />
To see the Type Hierarchy, open the view by choosing Window, Show View, Hierarchy. The new pane will appear within your Eclipse window. Choose an inheriting class in your application and right-click on a reference to the class name in one of your Java files, then choose Open Type Hierarchy. You should see the hierarchy presented within the new view. All classes in Java ultimately inherit from the class Object, so you will see it at the top of the hierarchy tree structure.<br />
<br />
<hr /><b>Conclusion</b><br />
<br />
Through OO development, you can work with re-usable code components which preserve the ability to specialise in unique application areas. This is sometimes referred to as polymorphism. The model allows you to make use of a wealth of existing code resources within both the Java language and the Android platform itself.<br />
<br />
Regardless of your development background, learning the basics of Object Oriented development needn't be a difficult task, and can have a hugely positive impact on your Android projects.<br />
<br />
The OO model is often used by developers working in teams, who need to be able to use one another's code without having to understand the implementation details within any particular section. This idea of an application being made up of code excerpts, each of which has clearly defined behaviours, is the key one to understand, whether you're working with classes and interfaces from your own apps, from the Android platform or from the Java language itself.Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com6tag:blogger.com,1999:blog-8119365238245677514.post-22248685052284739782012-01-30T16:38:00.001+00:002012-02-23T15:40:58.303+00:00Android Text To Speech (TTS) BasicsWhen I originally attempted implementing TTS functionality in my apps I was yet again surprised by how few practical tutorials there were online. I wrote a detailed, practical one a while back for Mobiletuts+ which runs through a simple app with the Text To Speech engine functions: <a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-using-the-text-to-speech-engine/">Using the Text to Speech Engine</a><br />
<br />
However, if you just want to know the basics so that you can get stuck into adding the functionality to create your own Text To Speech apps, here's what you need to do:<br />
<br />
<b>Import the TTS Classes</b><br />
To make use of the Text To Speech API, you need to reference it in your code. Add these import statements to your chosen class for standard functionality - includes the TTS resources and others necessary for basic tasks:<br />
<br />
<pre class="java" name="code">import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.content.Intent;
import java.util.Locale;
</pre><br />
<b>Implement the OnInitListener Interface</b><br />
When using the TTS functions you configure your speech functionality in the onInit method, so you need your class to implement this interface. Add "implements OnInitListener" to the class declaration in which you plan on providing TTS. The following sample code demonstrates:<br />
<br />
<pre class="java" name="code">public class MyLovelyClass extends Activity implements OnInitListener
</pre><br />
<b>Check for User Data</b><br />
Before you start making your apps speak you need to check that the user has the required resources on their device. Add the following instance variable at the top of your class declaration:<br />
<br />
<pre class="java" name="code">private int DATA_CHECKING = 0;
</pre><br />
Next add the data checking code to the section of your class that executes when it starts up. I.E. for a standard Java class put it in the constructor method, for an Activity class put it in "onCreate" and so on:<br />
<br />
<pre class="java" name="code">//create an Intent
Intent checkData = new Intent();
//set it up to check for tts data
checkData.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
//start it so that it returns the result
startActivityForResult(checkData, DATA_CHECKING);
</pre><br />
<b>Create a TTS Object</b><br />
So that you can access the Text To Speech object throughout the class, declare it as an instance variable at the top:<br />
<br />
<pre class="java" name="code">private TextToSpeech niceTTS;
</pre><br />
When the app receives the result of your data checking operation, the onActivityResult method will execute, so add the code to instantiate the TTS in there:<br />
<br />
<pre class="java" name="code">protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//do they have the data
if (requestCode == DATA_CHECKING) {
//yep - go ahead and instantiate
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
niceTTS = new TextToSpeech(this, this);
//no data, prompt to install it
else {
Intent promptInstall = new Intent();
promptInstall.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(promptInstall);
}
}
}
</pre><br />
Most users do have the TTS data now but this code takes care of those cases where they don't.<br />
<br />
<b>Provide the onInit Method</b><br />
Your class is extending the OnInitListener interface so that you can set the TTS object up to function when it initialises. Add the method as follows:<br />
<br />
<pre class="java" name="code">public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
niceTTS.setLanguage(Locale.UK);
}
}
</pre><br />
This is the basic process for choosing UK English but the engine offers a wide range of possibilities.<br />
<br />
<b>Say It Loud</b><br />
Now all you need to do is speak. Add this code wherever you want the speech to occur, passing a text string to speak:<br />
<br />
<pre class="java" name="code">String myWords = "I love you";
niceTTS.speak(myWords, TextToSpeech.QUEUE_FLUSH, null);
</pre><br />
This instructs the app to speak straight away, but you can optionally choose to add it to a queue, waiting for any existing speech to finish. Again, there are lots of options to explore.<br />
<br />
These are the basics of creating a TTS app on Android, but as mentioned above there are plenty of areas in which you can tailor and adapt the functionality.<br />
<br />
<i>If you're having trouble getting this to work in your apps, have a go at my other tutorial first, then try doing it with your own apps again: <a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-using-the-text-to-speech-engine/">Using the Text to Speech Engine</a></i><br />
<br />
<b>Other resources:</b><br />
<a href="http://developer.android.com/resources/articles/tts.html">Android Developer Guide: Using Text-to-Speech</a><br />
<a href="http://developer.android.com/reference/android/speech/tts/TextToSpeech.html">Android Developer Reference: public class TextToSpeech</a>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-1687220819381804662011-10-09T20:25:00.008+01:002012-02-23T15:38:18.235+00:00Adding a Share Button to Your Android Apps<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZkjQpNT2whtZUm00Wr8BF-1OBgkHs4on28fBV5bzxlRIk_KaflxgeHL7287slXGE0XuvoA0pfJJAhnktTbO1vow_3loJOA8oL7JKgWCsZYSERQIS5SzkaLTE0eDCZBAHjsfN7bDVLIR7c/s1600/sharebtn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZkjQpNT2whtZUm00Wr8BF-1OBgkHs4on28fBV5bzxlRIk_KaflxgeHL7287slXGE0XuvoA0pfJJAhnktTbO1vow_3loJOA8oL7JKgWCsZYSERQIS5SzkaLTE0eDCZBAHjsfN7bDVLIR7c/s1600/sharebtn.png" /></a> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWMZFezVxP3LGzdiUmDEkwPc9u3Q3jUCwzvvS5LcyTiDyYeiLdN7sXNYmrZmX9EPC562HCZeYCU3-wzEwQj0SZq_ZwFn-35KAZurUo4wYcfGCpBV5JVzA0sKImdxj4II1dW5jUaRvCsFk4/s1600/sharelist.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWMZFezVxP3LGzdiUmDEkwPc9u3Q3jUCwzvvS5LcyTiDyYeiLdN7sXNYmrZmX9EPC562HCZeYCU3-wzEwQj0SZq_ZwFn-35KAZurUo4wYcfGCpBV5JVzA0sKImdxj4II1dW5jUaRvCsFk4/s320/sharelist.png" width="320" /></a></div><b><i>The share button and list for one of my apps.</i></b><br />
<br />
I recently approached what I assumed would be the simple task of adding a share button to <a href="https://market.android.com/developer?pub=BeNormal">my Android apps</a>. While the implementation is indeed simple, I was disappointed, yet again, by the lack of easily digestible guidance online, for what must be a very common task.<br />
<br />
Anyway, for anyone in the same boat, here's what I learned. For my purposes I only needed a very basic implementation, so it may not be sufficient for your own applications - it should give you the generic outline in any case.<i> For more specific guidance see my Mobiletuts+ tutorial - <a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-implement-a-share-intent/">Android SDK: Implement a Share Inten</a><a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-implement-a-share-intent/">t</a> on </i><i>the </i><i>subject.</i><br />
<br />
<u><span style="font-size: small;"><b>Share Intent</b></span></u><br />
<br />
To create a share button you have to start a new Intent, passing it the SEND action. When the Activity for your SEND Intent starts, it will present the user with a list of possible channels to share the content through. What each user sees will depend on their own device setup, but it will typically include email, Gmail, Twitter, Facebook, text messaging etc. You will almost certainly have seen the share button in action as an Android user, for example in the browser program.<br />
<br />
Here is a basic outline of the code involved in instantiating a share button with the chooser list:<br />
<br />
<pre class="java" name="code">//create the send intent
Intent shareIntent =
new Intent(android.content.Intent.ACTION_SEND);
//set the type
shareIntent.setType("text/plain");
//add a subject
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
"Insert Subject Here");
//build the body of the message to be shared
String shareMessage = "Insert message body here.";
//add the message
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT,
shareMessage);
//start the chooser for sharing
startActivity(Intent.createChooser(shareIntent,
"Insert share chooser title here"));
</pre><br />
The code first creates an Intent with SEND as the action. The "setType" method allows you to choose a MIME type for the content being shared, such as plain text or HTML. The code here features two calls to the "putExtra" method, through which you can set various elements of your share item, subject and text content in this case. Finally, the code starts the Activity using the Intent sharing settings indicated, instructing Android to create a chooser list allowing users to pick a sharing medium.<br />
<br />
There are other options within the sharing implementation, and you can obviously alter the parameters, method calls etc. to suit your own apps. What options you pick really depends on what you're sharing.<br />
<br />
<u><span style="font-size: small;"><b>Considerations</b></span></u> <br />
<br />
Bear in mind the fact that certain aspects of what you set using "putExtra" will be irrelevant for certain sharing channels. For example, if you choose to set a title like I have, it won't appear if the user opts to share using a text message. Also, if you want your users to share using Twitter, remember the 140 character limit.<br />
<br />
It's actually tricky to create sharing content that will suit all of the possible messaging services. If you don't want users to choose from the list of options you can bypass that part of the process, but that means you have to create a button or other user control for each messaging service you want users to choose from.<br />
<br />
As well as providing the highest level of choice for your users, in my view it's best to use familiar interaction where possible, and Android users are by now accustomed to the sharing chooser list. The downside is that you need to keep your sharing content pretty simple and standard.<br />
<br />
For my apps, I was tempted to include a Twitter hashtag in the share content, since <a href="http://twitter.com/BrainDeadAir">it suits my content</a>, but clearly it would be redundant for users sharing through services other than Twitter. Obviously users can edit the content before going ahead and sending it, but it would be poor practice to include a load of guff the user has to delete each time they want to share something. <i>I've seen some apps in which the developer has crammed a load of publicity text including links etc. in with their sharing content - tempting, but not to be recommended from a usability point of view.</i><br />
<br />
<u><span style="font-size: small;"><b>Resources</b></span></u><br />
<br />
Hope that proved useful to some people, here are some related resources:<br />
<ul><li><a href="http://developer.android.com/guide/practices/ui_guidelines/activity_task_design.html">Android Developers: Activity and Task Design Guidelines</a></li>
<li><a href="http://developer.android.com/reference/android/content/Intent.html">Android Developers: Intent</a></li>
<li><a href="http://mobile.tutsplus.com/tutorials/android/android-email-intent/">Mobile tuts+: Enabling Users to Send Email From Your Android Applications</a></li>
</ul><br />
<b><i>Please feel free to add any of your own tips for sharing in Android apps.</i></b><br />
<br />
<u><b>Update November 2011</b></u><br />
I've written a tutorial on share buttons for Mobiletuts+ <a href="http://mobile.tutsplus.com/tutorials/android/android-sdk-implement-a-share-intent/">Android SDK: Implement a Share Intent</a> which goes into more detail.<b><i><br />
</i></b>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com10tag:blogger.com,1999:blog-8119365238245677514.post-57857278411693751812011-04-29T00:39:00.008+01:002011-09-30T22:17:10.942+01:00Android Market Comments and Ratings<i>As with all Internet and digital discourse, trolls seem to be a part of reality in the Android Market. </i><i>Some thoughts on the Android Market comments and ratings I've received to date. </i><br />
<br />
My Android apps are pretty niche, and I'm fully aware that they will only ever appeal to a small number of geeks like me. In the future I intend to develop apps that are more likely to be useful to a wide variety of users, but the apps I have on the Market at the moment are pretty odd.<br />
<br />
However narrow their appeal, I've always tried to indicate very clearly what my apps do in the descriptions within their Market listings. I naively assumed that people who had no interest in the functionality my apps provide would not download them in the first place, but this appears to have been a mistaken assumption. Lots of my reviews seem to be from people who have absolutely no interest in what my apps do (which is clearly indicated in the descriptions) but who have for some reason downloaded them and subsequently given them a poor review.<br />
<br />
While I've always been aware that a certain element of nastiness is standard within any Internet based review system, and know all about trolls and trolling, I must admit I've found my own feedback a little demoralising at times.<br />
<br />
Here are a few choice 1 star reviews (the minimum possible rating) I've received for my <a href="https://market.android.com/details?id=info.benormal.nonsense&feature=search_result">Nonsense</a> app, which is free by the way:<br />
<br />
<ul><li>"Does what it says. However its nonsense."</li>
<li>"Does what it says...NONSENSE!!!"</li>
<li>"Boring, tis nonsense but not funny at all"</li>
<li>"this game sucks!" <i>//nb the app is not meant to be a game</i></li>
<li>"Stinks!!!!"</li>
<li>"This the dummiest crap ever!!?? It is not wat I wanted."</li>
<li>"Stupid.. don't download"</li>
<li>"Gay!"</li>
<li>"Not amusing at all."</li>
<li>"Wow...waste of 4 sec. Of my life."</li>
<li>"Laaaaaame! Don't do it"</li>
<li>"Dumb...Uninstalled."</li>
<li>"i agree this is stupid and pointless"</li>
<li>"Crap...don't waste ur time downloading.... lame"</li>
<li>"Horrible, very stupid"</li>
<li>"Its stupid!!"</li>
<li>"Super lame."</li>
<li>"Worst app EVER!"</li>
<li>"The shittiest app I've ever seen"</li>
<li>"Boring pointless etc worst app ever do not download this..."</li>
<li>"Rlly retarded"</li>
<li>"Dumb!! Nothing good at all about this.."</li>
<li>"Pointless and stupid."</li>
<li>"This sucked! Waste of time!"</li>
<li>"Sucks"</li>
<li>"Terrible."</li>
<li>"I hate it"</li>
<li>"This is the most stupid thing ever don't get this!!"</li>
<li>"Why anyone would want this is beyond me!"</li>
<li>"This thing is almost as fun as going in the street and smashing your balls in with a hammer. This comment is officially better than this app"</li>
<li>"This sucks and it makes NO sense at all! Removing app" <i>//nb the app is called nonsense</i></li>
<li>"This was a waist of time and space. I mean there are some bad aps out there but this one is the worse of all"</li>
<li>"Zzzzzzzzz...boring on ov de worst games ever"</li>
<li>"Its F***ING stupid"</li>
<li>"Pointless...don't get it uninstalled. How do u even play this game?"</li>
<li>"Title is accurate. Don't waste time downloading this."</li>
</ul><br />
Just to explain, all the app really does is generate nonsense sentences. There's a bit of linguistic geekery involved in that the structures are grammatical and meaningless, but essentially it's just a bit of fun. The free version was my initial foray into Android development but in more recent months I've created a couple of slightly more sophisticated paid versions (including a sweary one).<br />
<br />
Anyway, from my point of view what's happened here is that I've spent a significant amount of my time producing and releasing something people can have for free if they happen to want it, and the overwhelming majority of those who have added a comment have responded with anger and some pretty vicious contempt, while in some cases acknowledging the fact that the app is exactly as described. Is it me or is there something wrong here?<br />
<br />
<i><b>An analogy: you see a stand in the street with the words "free chocolate ice cream" displayed above it, you go up and get some, eat a mouthful, spit it out and then start shouting about the fact that you hate chocolate ice cream...</b></i><br />
<br />
I do realise a certain amount of unfettered nastiness is generally inevitable in the context of digital communications, you only need to look at the comments section on any website to see that. However, as a developer basically creating trivial little apps for fun in my spare time, it does take the shine off things somewhat.<br />
<br />
To be fair, some of the comments I've had have been really productive and encouraging, and some of them have actually responded to the idiotic, nasty ones. I suspect some of the more helpful comments are perhaps from other developers, so I now make a point of putting positive comments on any apps I use that seem to be receiving a similar level of unwarranted aggression. However, my apps seem to have attracted this extreme negativity in the overwhelming majority of total feedback.<br />
<br />
Anyway, to finally get to the point, I've become aware recently that I, and I think most Internet users, just accept this nastiness as a necessary evil. However, I received an email the other day which chimed with some of what I've read in the press in the last while, from an organisation called <a href="http://civilinationnews.org/">CiviliNation</a> dedicated to campaigning against online bullying and the general lack of civility in digital discourse, and it got me questioning some of what I've accepted.<br />
<br />
It does seem that the tide may be turning slightly and that the days of totally unfettered bile online are probably numbered, in certain contexts anyway. While one of the great things about Internet communication is the lack of censorship, I don't think it follows from that that the normal expectations we have when interacting with people should not apply to digital communications also.<br />
<br />
The reality is that bullying has a very serious impact on some people, as the never-ending stream of stories about people announcing planned suicides on social networks demonstrates comprehensively. While this is the extreme end of the issue, I think the time has now come for us to have higher expectations of online behaviour.<br />
<br />
Ultimately the problem lies with a lack of responsibility, but the difficulty is going to lie in making people behave in a more civil way while still preserving a degree of anonymity. How we're going to improve the situation I really don't know, but a healthier breed of online discourse would surely be better for everyone involved.<br />
<br />
Here's some related content:<br />
<ul><li><a href="http://androinica.com/2010/09/5-rules-of-android-market-comment-etiquette/">Andronica - 5 Rules of Android Market Comment Etiquette</a></li>
<li><a href="http://apprssd.com/2011/03/21/android-market-comments-rating-system/">AppRSSd - Android Market Comments & Rating System</a></li>
<li><a href="http://www.mobilecrunch.com/2008/12/12/best-of-stupid-android-market-comments-by-slightly-stupid-people/">MobileCrunch - Best of: Stupid Android Market comments by slightly stupid people</a></li>
<li><a href="http://www.nytimes.com/2008/08/03/magazine/03trolls-t.html">The New York Times - The Trolls Among Us</a></li>
<li><a href="http://www.newscientist.com/blog/technology/2007/11/dont-flame-me-bro.html">New Scientist - Don't flame me, bro'</a></li>
<li><a href="http://www.guardian.co.uk/technology/2010/dec/12/aleks-krotoski-hate-internet-racism">Guardian - Hate and the internet</a></li>
<li><a href="http://www.guardian.co.uk/theguardian/2009/nov/03/stephen-fry-twitter">Guardian - Stephen Fry's Twitter wobble: I know just how he feels</a> </li>
</ul><br />
<u><b>Update July 2011:</b></u><br />
A couple of interesting Guardian articles on related topics:<br />
<ul><li><a href="http://www.guardian.co.uk/technology/2011/jul/24/internet-anonymity-trolling-tim-adams">How The Internet Created An Age Of Rage</a></li>
<li><a href="http://www.guardian.co.uk/commentisfree/2011/jun/06/spotify-problem-getting-people-to-pay">If The Internet Gave Free Back Rubs...</a></li>
</ul><br />
The first one is a fascinating look at the history and psychology of "trolling" with reference to anonymity and the second is a Charlie Brooker article from last month on Spotify, not exactly the same topic but touches on some related issues.<br />
<br />
And a few more:<br />
<ul><li> <a href="http://www.readwriteweb.com/archives/open_thread_on_trolls_anonymity_making_the_interne.php">Read Write Web - On Trolls, Anonymity & Making the Internet a Better Place</a></li>
<li> <a href="http://thenextweb.com/uk/2010/01/14/anonymous-troll-commenter-revealed/">The Next Web - When an Anonymous Troll is Revealed</a></li>
<li> <a href="http://www.nytimes.com/2011/04/24/magazine/mag-24lede-t.html">New York Times - How to Unmask the Internet’s Vilest Characters</a></li>
<li> <a href="http://www.nytimes.com/2010/11/30/opinion/30zhuo.html">New York Times - Where Anonymity Breeds Contempt</a></li>
<li> <a href="http://www.techspot.com/news/44394-study-internet-trolls-are-drunk-with-power.html">TechSpot - Internet trolls are drunk with power</a></li>
</ul><u><b>Update September 2011:</b></u><br />
Interesting piece in the Guardian pointing out the fact that as with any social problem there's no easy fix and that the reasons for trolling are complex:<br />
<a href="http://www.guardian.co.uk/commentisfree/2011/sep/14/troll-sean-duffy-internet">Guardian: All you trolls out there - come out and explain yourself</a><br />
<br />
The issue is certainly a complex one, and it seems there isn't even a clear definition of trolling at this stage, in fact it probably refers to a range of distinct activities with different characteristics and effects. The days of unfettered Internet trolls definitely look to be coming to an end, but there may well be negative consequences for Internet discourse too, i.e. the inevitable reduction in privacy.<br />
<br />
Here's another incredibly depressing tale of extreme trolling:<br />
<a href="http://skepchick.org/2011/09/mom-dont-read-this/">Skepchick - Mom, Don't Read This</a><br />
<br />
Something has to change, surely...<br />
<ul></ul>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-69862339227438026962011-04-17T23:25:00.005+01:002012-02-23T15:37:09.537+00:00Android Developer Tutorial WebsitesI've been pretty disappointed by the lack of Android developer tutorials online and have often spent ages trying to find out how to do something that I thought would pop up instantly after a quick Google.<br />
<br />
Learning how to program for Android can be quite a task depending on your own background, so access to decent educational material is vital. From Android widget development to standard Android software app development and getting to grips with the Android SDK, there's potentially a lot to learn.<br />
<br />
Anyway, here are some of the better sources for Android developer tutorials I've come across. If I find any more I'll add them to the list, feel free to add comments with any you've discovered yourself!<br />
<br />
<a href="http://developer.android.com/resources/browser.html?tag=tutorial" linkindex="23">Android Developer Resources - Tutorials</a><br />
OK, it may seem obvious but there are so many different ways to browse the official developer guide for Android that I find it useful to have several different parts of it bookmarked...<br />
<br />
<a href="http://www.vogella.de/android.html">Vogella - Android Tutorials</a><br />
Lars Vogel's site is one I find myself returning to again and again. The tutorials are detailed and the techniques always best practice. Thoroughly recommended. <br />
<br />
<a href="https://www.ibm.com/developerworks/mydeveloperworks/bookmarks/html?tag=android&base=http://www.ibm.com/developerworks/library/&dwapp=Technical%20library&lang=en" linkindex="24">IBM DeveloperWorks</a><br />
The IBM site has loads of useful resources for many different types of development, and Android is no exception.<br />
<br />
<a href="http://www.anddev.org/android-tutorials-with-source-code-f39/" linkindex="25">anddev.org</a><br />
The anddev.org site is a must-bookmark for anyone getting started with Android development in my view. I've found information here on numerous occasions that I couldn't find anywhere else.<br />
<br />
<a href="http://www.helloandroid.com/tutorials" linkindex="26">Hello Android</a><br />
It's a bit of an arbitrary mix but some of the tutorials on the Hello Android site are really useful.<br />
<br />
<a href="http://mobile.tutsplus.com/?s=android" linkindex="27">Mobiletuts+</a><br />
The tutorials on the Tuts+ network all tend to be very detailed and in-depth, and the mobile site has quite a few good Android guides.<br />
<br />
<a href="http://www.curious-creature.org/category/android/" linkindex="28">Romain Guy</a><br />
This is a personal blog by an Android software engineer and has a really good range of Android developer tutorials on different topics.<br />
<br />
<a href="http://www.androidguys.com/category/tips-tools/" linkindex="29">Android Guys</a><br />
A lot of the articles in the Tips and Tools section of Android Guys are aimed at users rather than developers, but there are a few development topics in there.<br />
<br />
<a href="http://www.talkandroid.com/category/android-development/" linkindex="30">Talk Android</a><br />
Mostly news-focused but with some guides, Talk Android is always worth a look.<br />
<br />
<hr /><br />
Finally, here are links to some of mine on different sites:<br />
<ul><li><a href="http://coding.smashingmagazine.com/2011/11/04/getting-the-best-out-of-eclipse-for-android-development/">Smashing Magazine - Getting Best Use Out of Eclipse for Android Development</a> </li>
<li><a href="http://mobile.tutsplus.com/author/sue-smith/">Mobiletuts: Various</a></li>
<li><a href="http://marketplace.tutsplus.com/user/benormal">Tuts+ Marketplace</a></li>
</ul><br />
<i>That's it for the moment, if I remember or discover any more I'll add them.</i>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com5tag:blogger.com,1999:blog-8119365238245677514.post-20305055952935850762011-03-03T22:50:00.005+00:002012-02-23T15:33:48.070+00:00Android Marketplaces and DirectoriesThere are already a load of places people can download or access your Android applications, other than the official Market. If you're a developer, you'll naturally want to explore as many places to sell and list your app as possible.<br />
<br />
Some of the sites and applications describing themselves as marketplaces simply link into the Android Market, but on some of them you can upload and sell your apps directly. In this article I'll run through some of the main Android application stores I've found, focusing on those sites where you can distribute Android software, i.e. upload your Android APK files and sell them.<br />
<br />
On the directories, you can sometimes sign up for an account and alter the details listed for your apps. Here are some I've come across, I haven't tried them all so can't guarantee they're any good. Also, some of these are new services and are just starting out, so they don't always have much of a user base yet.<br />
<br />
<b>Make sure you check out the terms, FAQs etc on any service before taking the time to sign up, many of them have high minimum payouts and restrictions on where developers can be resident etc.</b><br />
<b> </b><br />
<b><a href="http://www.androidzoom.com/" linkindex="52">AndroidZoom</a></b><br />
AndroidZoom is an interface to the Android Market. As a developer you can link your app listings to your Google account, insert additional information about your apps and access additional data, just click the "I'm the developer" link on any of your app listings.<br />
<br />
<b><a href="http://andappstore.com/AndroidApplications/" linkindex="53">AndAppStore</a></b><br />
AndAppStore is a an Android app store aimed at catering to a wider variety of users than the mainstream market. As a user you need to install the app to access your downloads but can shop for them on a computer if you like.<br />
<a href="http://andappstore.com/AndroidApplications/register.jsp" linkindex="54">Developer signup</a><br />
<br />
<b><a href="http://slideme.org/" linkindex="55">SlideME</a></b><br />
SlideME is a community based marketplace for Android apps.<br />
<a href="https://slideme.org/en/user/register" linkindex="56">Developer signup</a><br />
<br />
<b><a href="http://www.androidpit.com/" linkindex="57">AndroidPIT</a></b><br />
AndroidPIT combines an app store with articles and news etc about Android.<br />
<a href="http://www.androidpit.com/en/android/registration/form?dev=1" linkindex="58">Developer signup</a><br />
<br />
<b><a href="http://andspot.com/index.cfm" linkindex="59">AndSpot</a></b><br />
AndSpot is a new social networking based app store offering increased exposure and data.<br />
<a href="http://www.workinbeta.com/register.cfm" linkindex="60">Developer signup</a><br />
<br />
<b><a href="http://appslib.com/applications/index.html" linkindex="61">AppsLib</a></b><br />
ApplsLib is an alternative marketplace for tablets running Android. To use the service as a customer you need to install the AppsLib application.<br />
<a href="http://appslib.com/developers/create_account.html" linkindex="62">Developer signup</a><br />
<br />
<b><a href="http://www.handango.com/" linkindex="63">Handango</a></b><br />
Handango is a major app store for platforms including Android, Blackberry, Windows Mobile, Symbian and Palm.<br />
<a href="http://www.handango.com/info/Partner.jsp?storeId=2218&deviceId=2433&platformId=80" linkindex="64">Developer signup</a><br />
<br />
<b><a href="http://appoke.com/" linkindex="65">Appoke</a></b><br />
Appoke uses social networking to aid app sales.<br />
<a href="http://appoke.com/user/signup" linkindex="66">Developer signup</a><br />
<br />
<b><a href="http://www.mobihand.com/" linkindex="67">MobiHand</a></b><br />
MobiHand is an app store for Android, Blackberry, iPhone, Symbian, Windows Mobile and Palm.<br />
<a href="http://corporate.mobihand.com/developers_signup.asp" linkindex="68">Developer signup</a><br />
<br />
<b><a href="http://www.getjar.com/" linkindex="69">GetJar</a></b><br />
GetJar is an app store for many different handsets and platforms.<br />
<a href="http://developer.getjar.com/" linkindex="70">Developer signup</a><br />
<br />
<b><a href="http://www.appstorehq.com/" linkindex="71">AppStoreHQ</a></b><br />
AppStoreHQ covers Android, iPhone and iPad, linking to the Android market for downloads and sales. You can <a href="http://www.appstorehq.com/developers/about" linkindex="72">claim your profile</a>.<br />
<br />
<b><a href="http://androlicious.com/" linkindex="73">Androlicious</a></b><br />
Androlicious is an interface for browsing the Android market, and you can link your apps to your Google account. You can <a href="http://androlicious.com/home/contact" linkindex="74">submit apps</a> and information to them via email.<br />
<br />
<b><a href="http://www.androlib.com/" linkindex="75">AndroLib</a></b><br />
AndroLib is another listings site, but they have quite a lot of informative statistics and charts on the app pages. You can claim your apps by clicking the "I am the developer" link on the listings page.<br />
<br />
<i>So that's it for now. There are also loads of app review sites, but that'll be for another post... If you know of any good Android market store sites please do add them in the comments.</i><br />
<br />
<b><u>Update October 2011</u></b><br />
<i> </i>In the short time since I wrote this post a load more marketplaces have started up and I have to admit I've totally lost track of them! One resource that may be useful for some developers is <a href="http://www.appbackr.com/">appbackr</a> which I've just heard about so know very little about. It provides an alternative way of funding your apps and handles the distribution side of things for you. <i><b>If anyone has experience using the service please do comment on how well (or not) it's worked for you.</b></i>Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0tag:blogger.com,1999:blog-8119365238245677514.post-35128766016920505502011-02-24T20:14:00.004+00:002011-10-11T10:23:37.916+01:00Thinking About Android Development?I started Android development in 2009, although when I say "started" that's exactly what I mean. I learned the basics, released a <a href="https://market.android.com/search?q=pub:BeNormal">really trivial free application</a> and then did nothing else with Android for about a year and a half.<br />
<br />
Having started getting back into Android development since the end of 2010, I've been surprised by the still relatively small number of useful Android development resources online. For that reason I thought I'd start a blog and keep note of the things I learn or come across as I go along, in case any of it proves useful for anyone else. This is going to be pretty simple stuff aimed at developers like myself who are really just doing Android on a casual basis.<br />
<br />
<span style="font-style: italic;">Some initial thoughts about the Android development process:</span><br />
<br />
Android development isn't what I expected it to be. My initial training was in Java programming for desktop applications, and I then got into Web and multimedia development (mainly so that I could work freelance). I've always loved Java development, and for that reason was excited by the possibility of getting paid to do it on a freelance basis.<br />
<br />
However, the Android development process bears more resemblance to Web development than the type of Java application development I was used to. This is probably good news for people who come from a Web background and want to get into Android. If, like me, your background has been more desktop-oriented, you might need to make a bit of a mental adjustment when you approach Android. I'd recommend reading up on the <a href="http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle" linkindex="16">Android Activity Lifecycle</a> before you get started, as this is the key concept to get to grips with when it comes to structuring your apps.Anonymoushttp://www.blogger.com/profile/08085981060976444149noreply@blogger.com0