RSS

Monthly Archives: November 2012

Getting an Android SD Card Image to work on Mac OS X

By Tetchro

hen I began experimenting with Android development one of the first hurdles I encountered was trying to get the emulator to recognize a fake sd card so that I could reference it in the emulator. There doesn’t seem to be a whole lot of resources out there for doing this on Mac OS X (at least that I could find, but usually I can’t find anything on the internet so what do I know?), so after finally figuring it out with the help of a few different websites, I thought I’d post it here for any one else struggling and also for my own reference in case I ever need to do it again! I’ll keep the steps as simple as possible after the initial step (getting Eclipse installed and all that jazz). Basically, we just want to create an .iso file and get Eclipse to recognize that it exists:

  1. Obviously, install Eclipse, the SDK, and the ADT plugin package on your Mac… here’s a link to instructions on how to do this. It should be pretty straightforward, although I found the Android Developer’s website a little confusing to navigate.
    http://developer.android.com/sdk/installing.html
  2. Once you run Eclipse and get everything set up, you should have a workspace (by default I believe it ends up in your Documents folder. So in my case, since my username is Riley, the /Users/Riley/Documents/workspace directory). We’ll use this to store our sd card (you don’t have to though… you can put it anywhere you’d like! My examples that follow use this directory)
  3. Open up Terminal (it’s in Applications -> Utilities -> Terminal for those of you who have lived sheltered lives!)
  4. The first thing you want to do it navigate to the “tools” folder inside the sdk folder you downloaded from the Android developers website. In my case, the folder is called “android-sdk-macosx” (I saw some examples with different names, so I just wanted to be clear here) and it’s located on my desktop. So in my case, I would write into terminal:
    cd /Users/Riley/Desktop/android-sdk-macosx/tools

    So, basically,

    cd [directory of sdk tools folder]

    That should be simple enough if you know where you put the folder!

  5. Next, you want to create an .iso file in your workspace directory. In my case, I wanted a 1gb (1024 mb) “fake” sdcard to play with, so I typed into Terminal:
    ./mksdcard 1024M /Users/Riley/Documents/workspace/sdcard1.iso

    This runs an application called mksdcard in the tools folder we navigated to before and creates a 1024 mb .iso file in the directory /Users/Riley/Documents/workspace/sdcard1.iso. I named my sdcard “sdcard1.iso,” but you can give it a different name, of course. The basic command of this structure is:

    ./mksdcard [size] [name and location of file to be created]

    Both of the terminal commands. Now the sdcard1.iso exists!

    If you just type “./mksdcard 1024M sdcard1.iso” it will create “sdcard1.iso” in the tools folder in the sdk.Here’s a link to some more information about mksdcard from the Android Developer website. The minimum size of the sdcard image is 9 mb, and the maximum size is 1023 gb (pretty generous!).

  6. Next, find your “sdcard1.iso” (or whatever you named it) file and double-click it. This will mount the image under “devices,” which can be found in finder under the name “SDCARD”. To stick some stuff on it (in the picture I put a few audio files on there. Android, when you first run the emulator from Eclipse, creates the “Android” and “LOST.DIR” folders automatically) just drag and drop as you would with a normal USB drive. 

    The newly created sdcard1.iso can be found in Finder under “Devices” with the name SDCARD.

  7. Fire up Eclipse and navigate to the project you want to use the sdcard in.
  8. Go to Run -> Debug Configurations
  9. Click the “Target” tab on the right side of the window that pops up, and find the “Additional Emulator Command Line Options” textbox. When you first open this window, YOU MAY NEED TO SCROLL DOWN IN THE FRAME TO SEE THIS BOX. To make life easier for yourself, you can also simply expand the “Debug Configurations” window, and the textbox at the bottom should appear. I mention this because I was an idiot and didn’t realize I had to scroll down at first and thought I was in the wrong place. :P
  10. Type in “-sdcard [directory of sdcard1.iso]” (without the quotes, as seen in the image below). In my case, I wrote:
    -sdcard /Users/Riley/Documents/workspace/sdcard1.iso
  11. Click “Apply”. This also updates the “Run Configurations” settings (also available under the “Run” menu), so you don’t need to alter those. 

    Debug configurations altered to include the sdcard1.iso image.

  12. You should now be able to access the (fake) sdcard by using the directory /sdcard/
    As for where you go now, that’s up to you!

I can try to answer any questions if you run into problems, but hopefully this offers some help for any one that was confused about this whole process. Good luck!

 

Copy from: http://www.lagserv.net/wp/2012/04/tutorial-getting-an-android-sd-card-image-to-work-on-mac-os-x/

Advertisements
 
Leave a comment

Posted by on November 20, 2012 in Android, Mac

 

Query MP3 Information using Android supported function

By Pete Houston

That was quite a hard time to look for a way to retrieve MP3 metadata (header info) in Android. Mr. Google this time also doesn’t work for me _ _!

After a while looking around at Android Developers’ Reference, I’ve found one interesting class:MediaMetadataRetriever class, look at here. It seems like doing the function of retrieving music file header, like MP3 header information. So I give it a try and this is result:

Results from MediaMetadataRetriever

Results from MediaMetadataRetriever

It really looks good as you see! It’s better than the handy one in my previous post on getting MP3 basic information.

Give it a try:

 

01 package pete.android.study;
02
03 import android.app.Activity;
04 import android.media.MediaMetadataRetriever;
05 import android.os.Bundle;
06 import android.widget.TextView;
07
08 public class MainActivity extends Activity {
09     /** Called when the activity is first created. */
10     @Override
11     public void onCreate(Bundle savedInstanceState) {
12         super.onCreate(savedInstanceState);
13         setContentView(R.layout.main);
14
15         TextView tvMain = (TextView)findViewById(R.id.tvMain);
16         // load data file
17         MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
18         metaRetriever.setDataSource("/sdcard/music.mp3");
19
20         String out = "";
21         // get mp3 info
22         out += metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
23         out += "\n";
24         out += metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
25         out += "\n";
26         out += metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
27         out += "\n";
28         out += metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
29         out += "\n";
30         // convert duration to minute:seconds
31         String duration = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
32         long dur = Integer.parseInt(duration);
33         String seconds = String.valueOf(dur % 60);
34         String minutes = String.valueOf(dur / 60000);
35         out += "Length: [ " + minutes + "m" + seconds + "s ]\n";
36
37         // close object
38         metaRetriever.release();
39         // display output
40         tvMain.setText(out);
41     }
42 }

 

I’m quite surprised because of the result by using MediaMetadataRetriever, so simple and effective; also, just cannot believe that I cannot find any article on Internet about using this for querying Media or MP3 information.
I guess this article probably helps many of you in difficulties.
Hope you like it!

Browse source code from Android-Newbie Repository

Cheers,
Pete Houston

Parsing MP3 Basic Info manually

Let’s continue from my previous article on MP3 file structure.

We’re going into practice to parse MP3 basic info: Title, Artist, Year, Album. These are the most basic ones and we can achieve by reading the very last 128 bytes at the end of file.

First you need to put the file into Emulator, in my case, I put into “/sdcard/music.mp3“. After parsing just display it to screen:

MP3 Info Parsing

MP3 Info Parsing

Think it simple, just Java, no Android thought here!

This is how I did it :)

 

001 package pete.android.study;
002
003 import java.io.File;
004 import java.io.FileInputStream;
005 import java.io.FileNotFoundException;
006 import java.io.IOException;
007 import java.util.Calendar;
008 import java.util.HashMap;
009
010 public class MP3HeaderInfo {
011
012     // --- { constants } --- >>>
013     // ID3 tag value
014     public static final String ID3_TAG = "TAG";
015     public static final int BYTE_128 = 128;
016     public static final int[] OFFSET_TAG = new int[] { 03 };
017     public static final int[] OFFSET_TITLE = new int[] { 333 };
018     public static final int[] OFFSET_ARTIST = new int[] { 3363 };
019     public static final int[] OFFSET_YEAR = new int[] { 9397 };
020     public static final int[] OFFSET_ALBUM = new int[] { 6393 };
021
022     // indexer
023     public static final int FROM = 0;
024     public static final int TO = 1;
025
026     // key attribute
027     public static final String TITLE = "Title";
028     public static final String ARTIST = "Artist";
029     public static final String YEAR = "Year";
030     public static final String ALBUM = "Album";
031
032     // default values for each key value
033     public static final String DEFAULT_TITLE = "Unknown Title";
034     public static final String DEFAULT_ARTIST = "Unknown Artist";
035     public static final String DEFAULT_YEAR = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
036     public static final String DEFAULT_ALBUM = "Unknown Album";
037     // --- { constants } --- <<<
038
039     // --- { fields } --- >>>
040     private String mFile;
041     private String mTitle = DEFAULT_TITLE;
042     private String mArtist = DEFAULT_ARTIST;
043     private String mYear = DEFAULT_YEAR;
044     private String mAlbum = DEFAULT_ALBUM;
045     private String mErrorLog; // for error information
046     // --- { fields } --- <<<
047
048     // --- { constructor } --- >>>
049     public MP3HeaderInfo(String file) {
050         mFile = file;
051         // auto parse file, only once
052         parseAudio();
053     }
054     // --- { constructor } --- <<<
055
056     // --- { properties } --- >>>
057     public String getTitle() {
058         return !mTitle.equals("") ? mTitle.trim() : DEFAULT_TITLE;
059     }
060
061     public String getArtist() {
062         return !mArtist.equals("") ? mArtist.trim() : DEFAULT_ARTIST;
063     }
064
065     public String getYear() {
066         return !mYear.equals("") ? mYear.trim() : DEFAULT_YEAR;
067     }
068
069     public String getAlbum() {
070         return !mAlbum.equals("") ? mAlbum.trim() : DEFAULT_ALBUM;
071     }
072
073     public String getErrorLog() {
074         return mErrorLog;
075     }
076     // --- { properties } --- <<<
077
078     // --- { private methods } --- >>>
079     private boolean parseAudio() {
080         // create MP3 File object
081         File mp3 = new File(mFile);
082         FileInputStream fis;
083         try {
084             // create new file stream for parsing file in binary
085             fis = new FileInputStream(mp3);
086             // get file size
087             int size = (int) mp3.length();
088             // offset to the first byte of the last 128 bytes
089             fis.skip(size - BYTE_128);
090             // read chunk of 128 bytes
091             byte[] chunk = new byte[BYTE_128];
092             fis.read(chunk);
093             // convert chunk to string
094             String id3 = new String(chunk);
095             // get first 3 byte
096             String tag = id3.substring(OFFSET_TAG[FROM], OFFSET_TAG[TO]);
097             // if equals to "TAG" meaning a valid readable one
098             if(tag.equals(ID3_TAG)) {
099                 mTitle = id3.substring(OFFSET_TITLE[FROM], OFFSET_TITLE[TO]);
100                 mArtist = id3.substring(OFFSET_ARTIST[FROM], OFFSET_ARTIST[TO]);
101                 mYear = id3.substring(OFFSET_YEAR[FROM], OFFSET_YEAR[TO]);
102                 mAlbum = id3.substring(OFFSET_ALBUM[FROM], OFFSET_ALBUM[TO]);
103             }
104
105             // close stream after done
106             fis.close();
107             // return complete
108             return true;
109         catch (FileNotFoundException e) {
110             // log error
111             mErrorLog = e.getMessage();
112             return false;
113         catch (IOException e) {
114             // log error
115             mErrorLog = e.getMessage();
116             return false;
117         }
118     }
119
120     // --- { private methods } --- <<<
121
122     // --- { public methods } --- >>>
123     public static HashMap<String, String> getInfo(String file) {
124         HashMap<String, String> result = new HashMap<String, String>();
125         MP3HeaderInfo info = new MP3HeaderInfo(file);
126         result.put(ARTIST, info.getArtist());
127         result.put(TITLE, info.getTitle());
128         result.put(YEAR, info.getYear());
129         result.put(ALBUM, info.getAlbum());
130
131         return result;
132     }
133     // --- { public methods } --- <<<
134
135 }

 

For MainActivity, just input file name to parse and display:

 

01 package pete.android.study;
02
03 import java.util.HashMap;
04
05 import android.app.Activity;
06 import android.os.Bundle;
07 import android.widget.TextView;
08
09 public class MainActivity extends Activity {
10     /** Called when the activity is first created. */
11     @Override
12     public void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14         setContentView(R.layout.main);
15
16         TextView tvMain = (TextView)findViewById(R.id.tvMain);
17
18         HashMap<String, String> info = MP3HeaderInfo.getInfo("/sdcard/music.mp3");
19
20         String out = "";
21         out += info.get("Title") + " - " + info.get("Year") + "\n";
22         out += info.get("Album") + "\n" + info.get("Artist") + "\n";
23         tvMain.setText(out);
24     }
25 }

 

Very very basic of Java file handling, isn’t it?
Talking about MP3 Song Duration or Bit-rate, well, it’s quite complicated … I’m still not good enough at parsing them at the moment, it would take some more time to study about.
However, I guess those above info is enough to display to users. Or you can even achieve reading more metadata on MP3 file by using third-party libraries for your applications.
Have fun!

Cheers,
Pete Houston

Categories:TutorialsTags:

A Quick Study on MP3 file structure

Just had a little time playing around with MP3 file and found it quite interesting.

Do you like “New Divide” by Linkin Park, which is the Original Sound Track on Transformer 2: The Revenge of the Fallen? I personally like it very much. Ah right, Transformer 3 – Dark of the Moon is coming tomorrow, certainly I’ll watch it :D .

If you have the MP3 file of the song, on Windows Explorer right click on it and select Properties, open tab Details:

Windows Explorer: MP3 File Properties

Windows Explorer: MP3 File Properties

You can see its information like: Title, Artists, Album, Year, Genre, Length ….

Ok, try to open it using Mp3tag (v2.49):

MP3Tag - File Info View

MP3Tag – File Info View

The tag version of MP3 file is: ID3v2.3, which is basically derived from v1 and v2.3. Let’s have a look at the internal structure of ID3v1:

Internal layout of an ID3v1 tagged file.Internal layout of an ID3v1 tagged file.

At the description at original page about ID3v1,

Song Title 30 characters
Artist 30 characters
Album 30 characters
Year 4 characters
Comment 30 characters
Genre 1 byte

If you one sum the the size of all these fields we see that 30+30+30+4+30+1 equals 125 bytes and not 128 bytes. The missing three bytes can be found at the very beginning of the tag, before the song title. These three bytes are always “TAG” and is the identification that this is indeed a ID3 tag. The easiest way to find a ID3v1/1.1 tag is to look for the word “TAG” 128 bytes from the end of a file. ” – Quoted from ID3.org

Another pages on MP3 internal:

http://www.multiweb.cz/twoinches/mp3inside.htm

http://www.fortunecity.com/underworld/sonic/3/id3tag.html

So we can easily extract any MP3 file tag information by parsing its very last 128 bytes (128 bytes at the end).

Once again, I open the song in a hex editor:

Hex Editor: MP3 Binary Format

Hex Editor: MP3 Binary Format

That’s right, the info is there!

Generally, instead of reading MP3 file header structure at beginning, we can use the very last 128 bytes to extract its basic info. Interesting, isn’t it?

We’re gonna make a library to query MP3 basic info using Java on Android in next article :)

Just take a cup of coffee and enjoy the song “….give me reason …. connect the space between …” , lol :) )

 

Copy from: http://xjaphx.wordpress.com/tag/mp3/

 
Leave a comment

Posted by on November 16, 2012 in Android