NOTE #1: This tutorial was written for Android v1.0. I have just updated theAndroid streaming media player tutorial/code to v1.5 (Cupcake) with some additional information on the updated code. You should read that post as well as this one.
NOTE #2: This tutorial is about progressive audio. If you want to stream live media, then please read my post on live and progressive streaming with Android.
This is a long tutorial, but for those of you that have been struggling with streaming of .mp3 audio to Google’s Android’s MediaPlayer, then I hope this tutorial proves useful as you finalize your entries into Google’s Android Challenge
This tutorial will show how to roll your own streaming audio utility for Android’s MediaPlayer. We will buffer 10 seconds of audio and start playing that audio while the rest of the audio loads in the background. We store the streamed audio locally so you could cache it on device for later use or simply let it be garbage collected.
Here’s the source code for those that just want to jump in. You’ll also notice code for the other tutorials as I didn’t have time to strip them out.
Here are a few screenshots of what we’ll be creating:
Basic Layout
The tutorial consists of just two classes:
Tutorial3: Contains the UI layout and process button clicks
StreamingMediaPlayer: Connects to the server, downloads audio into the buffer, and controls the functionality to ensure the audio continues to play seamlessly.
StreamingMediaPlayer: Connects to the server, downloads audio into the buffer, and controls the functionality to ensure the audio continues to play seamlessly.
We’ll assume you know about UI layout using Android’s XML resource files and will instead jump right into the audio streaming code.
Start Your Streaming
Upon clicking the “Start Streaming” button, Tutorial3 creates an instance of StreamingMediaPlayer.
new StreamingMediaPlayer(textStreamed, playButton, streamButton,progressBar);
All UI elements are passed to StreamingMediaPlayer so it can perform UI update itself. In a more robust implementation, StreamingMediaPlayer would fire relevant update events and Tutorial3 would handle the UI updates. For simplicity & cleaner code in this tutorial however, StreamingMediaPlayer will be directly updating the UI.
Tutorial3 then calls StreamingMediaPlayer.startStreaming():
audioStreamer.startStreaming(“http://www.pocketjourney.com/audio.mp3″,1444, 180);
Three variables are passed to startStreaming(): a url for the media to stream (link to an .mp3 file in this tutorial), the length in kilobytes of the media file, and the lenght in seconds of the media file. These last two values will be used when updating the progress bar.
AudioStreamer.startStreaming() creates a new thread for streaming the content so we can immediately return control back to the user interface.
public void startStreaming(final String mediaUrl, long mediaLengthInKb, long mediaLengthInSeconds) throws IOException {
this.mediaLengthInKb = mediaLengthInKb;
this.mediaLengthInSeconds = mediaLengthInSeconds;
this.mediaLengthInSeconds = mediaLengthInSeconds;
Runnable r = new Runnable() {
public void run() {
try {
downloadAudioIncrement(mediaUrl);
} catch (IOException e) {
Log.e(getClass().getName(), “Initialization error for fileUrl=” + mediaUrl, e);
return;
return;
}
}
};
new Thread(r).start();
new Thread(r).start();
}
Incremental Media Download
This is where the magic happens as we download media content from the the url stream until we have enough content buffered to start the MediaPlayer. We then let the MediaPlayer play in the background while we download the remaining audio. If the MediaPlayer reaches the end of the buffered audio, then we transfer any newly downloaded audio to the MediaPlayer and let it start playing again.
Things get a little tricky here because:
(a) The MediaPlayer seems to lock the file so we can’t simply append our content to the existing file.
(b) Pausing the MediaPlayer to load the new content takes awhile so we only want to interrupt it when absolutely necessary.
(c) Accessing the MediaPlayer from a separate thread causes it to crash.
(b) Pausing the MediaPlayer to load the new content takes awhile so we only want to interrupt it when absolutely necessary.
(c) Accessing the MediaPlayer from a separate thread causes it to crash.
So with those caveats in mind, here’s the method that bufferes the media content to a temporary file:
public void downloadAudioIncrement(String mediaUrl) throws IOException {
// First establish connection to the media provider
URLConnection cn = new URL(mediaUrl).openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null) {
URLConnection cn = new URL(mediaUrl).openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null) {
Log.e(getClass().getName(), “Unable to create InputStream for mediaUrl:” + mediaUrl);
}
// Create the temporary file for buffering data into
downloadingMediaFile = File.createTempFile(“downloadingMedia”, “.dat”);
FileOutputStream out = new FileOutputStream(downloadingMediaFile);
downloadingMediaFile = File.createTempFile(“downloadingMedia”, “.dat”);
FileOutputStream out = new FileOutputStream(downloadingMediaFile);
// Start reading data from the URL streambyte buf[] = new byte[16384];
int totalBytesRead = 0, incrementalBytesRead = 0;
do {
int totalBytesRead = 0, incrementalBytesRead = 0;
do {
int numread = stream.read(buf);
if (numread <= 0) {
if (numread <= 0) {
// Nothing left to read so quit
break;
break;
} else {
out.write(buf, 0, numread);
totalBytesRead += numread;
incrementalBytesRead += numread;
totalKbRead = totalBytesRead/1000;
totalBytesRead += numread;
incrementalBytesRead += numread;
totalKbRead = totalBytesRead/1000;
// Test whether we need to transfer buffered data to the MediaPlayer
testMediaBuffer();
// Update the status for ProgressBar and TextFieldsfireDataLoadUpdate();
testMediaBuffer();
// Update the status for ProgressBar and TextFieldsfireDataLoadUpdate();
}
} while (true);
// Lastly transfer fully loaded audio to the MediaPlayer and close the InputStream
fireDataFullyLoaded();
stream.close();
fireDataFullyLoaded();
stream.close();
}
What’s up with testMediaBuffer()?
So if you were paying attention, an important piece of functionality must reside in the testMediaBuffer() method. You’re right. That’s the method where we determine whether we need to transfer buffered data to the MediaPlayer because we have enough to start the MediaPlayer or because the MediaPlayer has already played out its previous buffer content.
Before we jump into that, please take note that interacting with a MediaPlayer on non-main UI thread can cause crashes so we always ensure we are interacting with the UI on the main-UI Thread by using a Handler when necessary. For example, we must do so in the following method because it is being called by the media streaming Thread.
private void testMediaBuffer() {
// We’ll place our following code into a Runnable so the Handler can call it for running
// on the main UI thread
Runnable updater = new Runnable() {
// on the main UI thread
Runnable updater = new Runnable() {
public void run() {
if (mediaPlayer == null) {
// The MediaPlayer has not yet been created so see if we have
// the minimum buffered data yet.
// For our purposes, we take the minimum buffered requirement to be:
// INTIAL_KB_BUFFER = 96*10/8;//assume 96kbps*10secs/8bits per byte
if ( totalKbRead >= INTIAL_KB_BUFFER) {
// the minimum buffered data yet.
// For our purposes, we take the minimum buffered requirement to be:
// INTIAL_KB_BUFFER = 96*10/8;//assume 96kbps*10secs/8bits per byte
if ( totalKbRead >= INTIAL_KB_BUFFER) {
try {
// We have enough buffered content so start the MediaPlayer
startMediaPlayer(bufferedFile);
startMediaPlayer(bufferedFile);
} catch (Exception e) {
Log.e(getClass().getName(), “Error copying buffered conent.”, e);
}
}
} else if ( mediaPlayer.getDuration() – mediaPlayer.getCurrentPosition() <= 1000 ){
// The MediaPlayer has been started and has reached the end of its buffered
// content. We test for < 1second of data (i.e. 1000ms) because the media
// player will often stop when there are still a few milliseconds of data left to play
transferBufferToMediaPlayer();
// content. We test for < 1second of data (i.e. 1000ms) because the media
// player will often stop when there are still a few milliseconds of data left to play
transferBufferToMediaPlayer();
}
}
};
handler.post(updater);
handler.post(updater);
}
Starting the MediaPlayer with Initial Content Buffer
Starting the MediaPlayer is very straightforward now. We simply copy all the currently buffered content
into a new Ffile and start the MediaPlayer with it.
into a new Ffile and start the MediaPlayer with it.
private void startMediaPlayer(File bufferedFile) {
try {
File bufferedFile = File.createTempFile(“playingMedia”, “.dat”);
FileUtils.copyFile(downloadingMediaFile,bufferedFile);} catch (IOException e) {
FileUtils.copyFile(downloadingMediaFile,bufferedFile);} catch (IOException e) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(bufferedFile.getAbsolutePath());
mediaPlayer.prepare();
fireDataPreloadComplete();
mediaPlayer.setDataSource(bufferedFile.getAbsolutePath());
mediaPlayer.prepare();
fireDataPreloadComplete();
Log.e(getClass().getName(), “Error initializing the MediaPlaer.”, e);
return;
return;
}
}
Transferring Buffered Content to a MediaPlayer That is Already Playing
This is a little trickier but not much. We simply pause the MediaPlayer if it was playing (i.e. the user had not pressed pause), copy over the currently downloaded media content (which may be all of it by now) and then restart the MediaPlayer if it was previously running or had hit the end of its buffer due to a slow network.
private void transferBufferToMediaPlayer() {
try {
// Determine if we need to restart the player after transferring data (e.g. perhaps the user
// pressed pause) & also store the current audio position so we can reset it later.
boolean wasPlaying = mediaPlayer.isPlaying();
int curPosition = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
// pressed pause) & also store the current audio position so we can reset it later.
boolean wasPlaying = mediaPlayer.isPlaying();
int curPosition = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
// Copy the current buffer file as we can’t download content into the same file that
// the MediaPlayer is reading from.
File bufferedFile = File.createTempFile(“playingMedia”, “.dat”);
FileUtils.copyFile(downloadingMediaFile,bufferedFile);
// the MediaPlayer is reading from.
File bufferedFile = File.createTempFile(“playingMedia”, “.dat”);
FileUtils.copyFile(downloadingMediaFile,bufferedFile);
// Create a new MediaPlayer. We’ve tried reusing them but that seems to result in
// more system crashes than simply creating new ones.
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(bufferedFile.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.seekTo(curPosition);
// more system crashes than simply creating new ones.
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(bufferedFile.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.seekTo(curPosition);
// Restart if at end of prior beuffered content or mediaPlayer was previously playing.
// NOTE: We test for < 1second of data because the media player can stop when there is still
// a few milliseconds of data left to play
boolean atEndOfFile = mediaPlayer.getDuration() – mediaPlayer.getCurrentPosition() <= 1000;
if (wasPlaying || atEndOfFile){
// NOTE: We test for < 1second of data because the media player can stop when there is still
// a few milliseconds of data left to play
boolean atEndOfFile = mediaPlayer.getDuration() – mediaPlayer.getCurrentPosition() <= 1000;
if (wasPlaying || atEndOfFile){
mediaPlayer.start();
}
}catch (Exception e) {
Log.e(getClass().getName(), “Error updating to newly loaded content.”, e);
}
}
Conclusion
To get the real feel for how your audio will download, make sure to set it to a slower network speed. I recommend setting to AT&T’s EDGE network setting as it should give a lower limit on expected performance. You can make these setting’s easy in Eclipse by setting going into your Run or Debug setting’s dialog and making these selections.
Well that’s it. I’ve inluded additional code for handling the ProgressBar and TextField updates but that should all be sufficiently easy to understand once you understand the rest of the code. Good luck during the next week as you finish your Android Challenge submissions.
And of course, here’s the source code. Please post a comment below if I need to explain anything in more detail. You’ll also notice code for the other tutorials as I didn’t have time to strip them out.
Android radio buttons example
1. Custom String
Open “res/values/strings.xml” file, add some custom string for radio button.
File : res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, MyAndroidAppActivity!</string> <string name="app_name">MyAndroidApp</string> <string name="radio_male">Male</string> <string name="radio_female">Female</string> <string name="btn_display">Display</string> </resources>
2. RadioButton
Open “res/layout/main.xml” file, add “RadioGroup“, “RadioButton” and a button, inside the
LinearLayout
.
File : res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <RadioGroup android:id="@+id/radioSex" android:layout_width="wrap_content" android:layout_height="wrap_content" > <RadioButton android:id="@+id/radioMale" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/radio_male" android:checked="true" /> <RadioButton android:id="@+id/radioFemale" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/radio_female" /> </RadioGroup> <Button android:id="@+id/btnDisplay" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_display" /> </LinearLayout>
Radio button selected by default.
To make a radio button is selected by default, put
To make a radio button is selected by default, put
android:checked="true"
within the RadioButton
element. In this case, radio option “Male” is selected by default.
3. Code Code
Inside activity “
onCreate()
” method, attach a click listener on button.
File : MyAndroidAppActivity.java
package com.mkyong.android; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Toast; public class MyAndroidAppActivity extends Activity { private RadioGroup radioSexGroup; private RadioButton radioSexButton; private Button btnDisplay; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); addListenerOnButton(); } public void addListenerOnButton() { radioSexGroup = (RadioGroup) findViewById(R.id.radioSex); btnDisplay = (Button) findViewById(R.id.btnDisplay); btnDisplay.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // get selected radio button from radioGroup int selectedId = radioSexGroup.getCheckedRadioButtonId(); // find the radiobutton by returned id radioSexButton = (RadioButton) findViewById(selectedId); Toast.makeText(MyAndroidAppActivity.this, radioSexButton.getText(), Toast.LENGTH_SHORT).show(); } }); } }
4. Demo
Run the application.
1. Result, radio option “Male” is selected.
2. Select “Female” and click on the “display” button, the selected radio button value is displayed.
Download Source Code HERE
Introduction to android Development
The BlackBerry and iPhone, which have appealing and high-volume mobile platforms, are addressing opposite ends of a spectrum. The BlackBerry is rock-solid for the enterprise business user. For a consumer device, it's hard to compete with the iPhone for ease of use and the "cool factor." Android, a young and yet-unproven platform, has the potential to play at both ends of the mobile-phone spectrum and perhaps even bridge the gulf between work and play.
Today, many network-based or network-capable appliances run a flavor of the Linux kernel. It's a solid platform: cost-effective to deploy and support and readily accepted as a good design approach for deployment. The UI for such devices is often HTML-based and viewable with a PC or Mac browser. But not every appliance needs to be controlled by a general computing device. Consider a conventional appliance, such as a stove, microwave or bread maker. What if your household appliances were controlled by Android and boasted a color touch screen? With an Android UI on the stove-top, the author might even be able to cook something.
In this article, learn about the Android platform and how it can be used for mobile and nonmobile applications. Install the Android SDK and build a simple application. Download the source code for the example application in this article.
The Android platform is the product of the Open Handset Alliance, a group of organizations collaborating to build a better mobile phone. The group, led by Google, includes mobile operators, device handset manufacturers, component manufacturers, software solution and platform providers, and marketing companies. From a software development standpoint, Android sits smack in the middle of the open source world.
The first Android-capable handset on the market was the G1 device manufactured by HTC and provisioned on T-Mobile. The device became available after almost a year of speculation, where the only software development tools available were some incrementally improving SDK releases. As the G1 release date neared, the Android team released SDK V1.0 and applications began surfacing for the new platform.
To spur innovation, Google sponsored two rounds of "Android Developer Challenges," where millions of dollars were given to top contest submissions. A few months after the G1, the Android Market was released, allowing users to browse and download applications directly to their phones. Over about 18 months, a new mobile platform entered the public arena.
With Android's breadth of capabilities, it would be easy to confuse it with a desktop operating system. Android is a layered environment built upon a foundation of the Linux kernel, and it includes rich functions. The UI subsystem includes:
- Windows
- Views
- Widgets for displaying common elements such as edit boxes, lists, and drop-down lists
Android includes an embeddable browser built upon WebKit, the same open source browser engine powering the iPhone's Mobile Safari browser.
Android boasts a healthy array of connectivity options, including WiFi, Bluetooth, and wireless data over a cellular connection (for example, GPRS, EDGE, and 3G). A popular technique in Android applications is to link to Google Maps to display an address directly within an application. Support for location-based services (such as GPS) and accelerometers is also available in the Android software stack, though not all Android devices are equipped with the required hardware. There is also camera support.
Historically, two areas where mobile applications have struggled to keep pace with their desktop counterparts are graphics/media, and data storage methods. Android addresses the graphics challenge with built-in support for 2-D and 3-D graphics, including the OpenGL library. The data-storage burden is eased because the Android platform includes the popular open source SQLite database. Figure 1 shows a simplified view of the Android software layers.
Figure 1. Android software layers
As mentioned, Android runs atop a Linux kernel. Android applications are written in the Java programming language, and they run within a virtual machine (VM). It's important to note that the VM is not a JVM as you might expect, but is the Dalvik Virtual Machine, an open source technology. Each Android application runs within an instance of the Dalvik VM, which in turn resides within a Linux-kernel managed process, as shown below.
Figure 2. Dalvik VM
An Android application consists of one or more of the following classifications:
- Activities
- An application that has a visible UI is implemented with an activity. When a user selects an application from the home screen or application launcher, an activity is started.
- Services
- A service should be used for any application that needs to persist for a long time, such as a network monitor or update-checking application.
- Content providers
- You can think of content providers as a database server. A content provider's job is to manage access to persisted data, such as a SQLite database. If your application is very simple, you might not necessarily create a content provider. If you're building a larger application, or one that makes data available to multiple activities or applications, a content provider is the means of accessing your data.
- Broadcast receivers
- An Android application may be launched to process a element of data or respond to an event, such as the receipt of a text message.
An Android application, along with a file called AndroidManifest.xml, is deployed to a device. AndroidManifest.xml contains the necessary configuration information to properly install it to the device. It includes the required class names and types of events the application is able to process, and the required permissions the application needs to run. For example, if an application requires access to the network — to download a file, for example — this permission must be explicitly stated in the manifest file. Many applications may have this specific permission enabled. Such declarative security helps reduce the likelihood that a rogue application can cause damage on your device.
The next section discusses the development environment required to build an Android application.
The easiest way to start developing Android applications is to download the Android SDK and the Eclipse IDE (see Resources). Android development can take place on Microsoft® Windows®, Mac OS X, or Linux.
This article assumes you are using the Eclipse IDE and the Android Developer Tools plug-in for Eclipse. Android applications are written in the Java language, but compiled and executed in the Dalvik VM (a non-Java virtual machine). Coding in the Java language within Eclipse is very intuitive; Eclipse provides a rich Java environment, including context-sensitive help and code suggestion hints. Once your Java code is compiled cleanly, the Android Developer Tools make sure the application is packaged properly, including the AndroidManifest.xml file.
It's possible to develop Android applications without Eclipse and the Android Developer Tools plug-in, but you would need to know your way around the Android SDK.
The Android SDK is distributed as a ZIP file that unpacks to a directory on your hard drive. Since there have been several SDK updates, it is recommended that you keep your development environment well organized so you can easily switch between SDK installations. The SDK includes:
- android.jar
- Java archive file containing all of the Android SDK classes necessary to build your application.
- documention.html and docs directory
- The SDK documentation is provided locally and on the Web. It's largely in the form of JavaDocs, making it easy to navigate the many packages in the SDK. The documentation also includes a high-level Development Guide and links to the broader Android community.
- Samples directory
- The samples subdirectory contains full source code for a variety of applications, including ApiDemo, which exercises many APIs. The sample application is a great place to explore when starting Android application development.
- Tools directory
- Contains all of the command-line tools to build Android applications. The most commonly employed and useful tool is the
adb
utility (Android Debug Bridge). - usb_driver
- Directory containing the necessary drivers to connect the development environment to an Android-enabled device, such as the G1 or the Android Dev 1 unlocked development phone. These files are only required for developers using the Windows platform.
Android applications may be run on a real device or on the Android Emulator, which ships with the Android SDK. Figure 3 shows the Android Emulator's home screen.
Figure 3. Android Emulator
The
adb
utility supports several optional command-line arguments that provide powerful features, such as copying files to and from the device. The shell command-line argument lets you connect to the phone itself and issue rudimentary shell commands. Figure 4 shows the adb
shell command against a real device connected to a Windows laptop with a USB cable.Figure 4. Using the
adb
shell command
Within this shell environment, you can:
- Display the network configuration that shows multiple network connections. Note the multiple network connections:
lo
is the local or loopback connection.tiwlan0
is the WiFi connection with an address provisioned by a local DHCP server.- Display the contents of the
PATH
environment variable. - Execute the
su
command to become the super-user. - Change the directory to /data/app, where user applications are stored.
- Do a directory listing where you see a single application. Android application files are actually archive files that are viewable with WinZip or equivalent. The extension is apk.
- Issue a ping command to see if Google.com is available.
From this same command-prompt environment, you can also interact with SQLite databases, start programs, and many other system-level tasks. This is fairly remarkable function, considering you're connected to a telephone.
In the next section, you'll create a simple Android application.
This section provides a whirlwind tour of building an Android application. The example application is about as simple as you can imagine: a modified "Hello Android" application. You'll add a minor modification to make the screen background color all white so you can use the phone as a flashlight. Not very original, but it will be useful as an example. Download the full source code.
To create an application in Eclipse, select File > New > Android project, which starts the New Android Project wizard.
Figure 5. New Android project wizard
Next, you create a simple application with a single activity, along with a UI layout stored in main.xml. The layout contains a text element you're going to modify to say Android FlashLight. The simple layout is shown below.
Listing 1. Flashlight layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/all_white"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textColor="@color/all_black" android:gravity="center_horizontal"/> </LinearLayout> |
Create a couple of color resources in strings.xml.
Listing 2. Color in strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Android FlashLight</string> <string name="app_name">FlashLight</string> <color name="all_white">#FFFFFF</color> <color name="all_black">#000000</color> </resources> |
The main screen layout has a background color defined as
all_white
. In the strings.xml file, you see that all_white
is defined as an RGB triplet value of #FFFFFF, or all white.
The layout contains a single
TextView
, which is really just a piece of static text; it is not editable. The text is set to be black and is centered horizontally with the gravity
attribute.
The application has a Java source file called FlashLight.java, as shown below.
Listing 3. Flashlight.java
package com.msi.flashlight; import android.app.Activity; import android.os.Bundle; public class FlashLight extends Activity { /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } |
The code is boiler-plate directly from the New Project wizard:
- It is part of a Java package called com.msi.flashlight.
- It has two imports:
- One for the activity class
- One for the bundle class
- When this activity is initiated, the
onCreate
method is invoked, passing in asavedInstanceState
. Don't be concerned with this bundle for our purposes; it is used when an activity is suspended and then resumed. - The
onCreate
method is an override of the activity class method of the same name. It calls the super class'sonCreate
method. - A call to
setContentView()
associates the UI layout defined in the file main.xml. Anything in main.xml and strings.xml gets automatically mapped to constants defined in the R.java source file. Never edit this file directly, as it is changed upon every build.
Running the application presents a white screen with black text.
Figure 6. White screen of flashlight
The AndroidManifest.xml file setup for the FlashLight application is shown below.
Listing 4. AndroidManifest.xml for FlashLight
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.msi.flashlight" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".FlashLight" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
This file was created automatically by the Android Developer Tools plug-in for Eclipse. You didn't have to do anything.
Of course, the application is not terribly magnificent. But it could come in handy if you want to do some reading without disturbing your sleeping spouse, or if you need to find your way to the fuse box in the basement during a power outage.
In this article, you learned about Android at a very high level and built a small application. Hopefully, the example got you excited enough to explore more of the Android platform. Android promises to be a market-moving open source platform that will be useful well beyond cell phones.
Season 1 → View Guide
Season 2 → View Guide
Season 3 → View Guide
I am very impressed with your writing skills, as well, with the provision contained in the written material weblog.your important to me, thanks for sharing with me ...
ReplyDeleteBuild Day Spa Mobile App
The link to source code is invalid. Can you re-upload it? Thank you!
ReplyDeletehi this is a good post, but when i have changed the other .mp3 url, then application getting freeze, the mp3 getting buffered but does not playing anything... i have changed the following URL
ReplyDeletehttps://ia600502.us.archive.org/12/items/Mp3Songs_175/hisss06www.songs.pk.mp3
please tell me if i have to stream a long mp3 file say 5mb or above, will it work for me or not????????
ReplyDeleteMens Titanium Wedding Rings
ReplyDeleteMens T-Shirts · titanium white dominus price Mens. Women's T-Shirts. Women's T-Shirts. Women's T-Shirt. Mens T-Shirts. Women's T-Shirts. Women's titanium exhaust wrap T-Shirts. Men's T-Shirts. Women's T-Shirts. Women's T-Shirts. Women's T-Shirts. Women's T-Shirts. titanium jewelry Women's titanium properties T-Shirts. Women's T-Shirts. babylisspro nano titanium Women's T-Shirts. Women's T-Shirts.