On Android simple-xml serial.read() throws StackOverflowError - java

I'm trying to learn to use xml in Java (Android platform, using Eclipse and simple-xml-2.5.2).
I keep getting a weird java.lang.StackOverflowError in the "serial.read" line in "Training.java".
Can you help fixing the problem? Is it an xml definition error?
I include the source below:
File beacons.java:
package com.marcos.training;
import java.util.List;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
#Element
public class Beacons {
#ElementList(inline=true)
private List<Beacon> list;
#Element
private String id;
public String getId() {
return id;
}
public Integer getSize() {
return list.size();
}
public List<Beacon> getList() {
return list;
}
}
File Beacon.java:
package com.marcos.training;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
#Root
public class Beacon {
#Attribute
protected String ssid;
#Element
protected String bssid;
public String getSsid() {
return ssid;
}
public String getBssid() {
return bssid;
}
}
File Training.java:
package com.marcos.training;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.content.res.Resources.NotFoundException;
public class Training extends Activity {
private final static String TAG = Training.class.getCanonicalName();
TextView textStatus;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textStatus = (TextView) findViewById(R.id.textStatus);
Serializer serial = new Persister();
try {
Beacons myBeacons;
try {
myBeacons = serial.read(Beacons.class, getResources().openRawResource(R.xml.beacons));
Log.i(TAG, "Number of Beacons: " + myBeacons.getSize());
} catch (NotFoundException e) {
Log.d(TAG, "Uncaught exception", e);
return;
} catch (Exception e) {
Log.d(TAG, "Uncaught exception", e);
return;
}
int len = myBeacons.getSize();
for (int i = 0; i < len; i++) {
Beacon b = myBeacons.getList().get(i);
textStatus.append("Beacon " + (i+1) + "\n");
textStatus.append(" SSID : " + b.getSsid() + "\n");
textStatus.append(" BSSID : " + b.getBssid() + "\n");
textStatus.append("\n");;
}
} catch (Exception e) {
Log.d(TAG, "Uncaught exception", e);
}
}
}
File beacons.xml:
<?xml version="1.0" encoding="utf-8"?>
<beacons id="1">
<beacon ssid="north">
<bssid>01:02:03:04:05:06</bssid>
</beacon>
<beacon ssid="east">
<bssid>02:03:04:05:06:07</bssid>
</beacon>
<beacon ssid="south">
<bssid>03:04:05:06:07:08</bssid>
</beacon>
<beacon ssid="west">
<bssid>04:05:06:07:08:09</bssid>
</beacon>
</beacons>

By putting your XML file into the XML directory of the resources, the Android build system is assuming you want that compiled down into a binary format and it obliges you. Therefore, when you access that input stream and then try to treat it as a textual XML representation it just doesn't work. You have 2 choices.
Move your XML file into the res\raw directory.
Leave it where it is and use the getResources().getXml(R.xml.beacons) API and create a pull parser for your particular XML.
See this link for more details.

Related

Using Gson For Json Post in Android

Following a tutorial which I didn't fully understand I did the following:
I created four classes.
package com.example.android.wearable.watchface;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
public class Beansubject {
#SerializedName("subject")
private static String subject;
#SerializedName("price")
private static String price;
#SerializedName("author")
private static String author;
#SerializedName("topics")
private static ArrayList<BeanTopic> beanTopics;
public Beansubject(ArrayList<BeanTopic> beanTopics, String subject, String price, String author) {
this.beanTopics = beanTopics;
this.subject = subject;
this.price = price;
this.author = author;
}
public static String getSubject() {
return subject;
}
public static void setSubject(String subj) {
subject = subj;
}
public static String getPrice() {
return price;
}
public static void setPrice(String pric) {
price = pric;
}
public String getAuthor() {
return author;
}
public static void setAuthor(String aue) {
author = aue;
}
public static ArrayList<BeanTopic> getBeanTopics() {
return beanTopics;
}
public static void setBeanTopics(ArrayList<BeanTopic> beantcs) {
beanTopics = beantcs;
}
}
Next
package com.example.android.wearable.watchface;
import com.google.gson.annotations.SerializedName;
public class BeanTopic {
#SerializedName("title")
private String title;
public BeanTopic(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Next
package com.example.android.wearable.watchface;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class API {
private static Reader reader=null;
public static Reader getData(String SERVER_URL) {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(SERVER_URL);
HttpResponse response = httpClient.execute(httpPost);
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
reader = new InputStreamReader(content);
} else {
// Log.e("error:", "Server responded with status code: "+ statusLine.getStatusCode());
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return reader;
}
}
Finally
package com.example.android.wearable.watchface;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import com.google.gson.GsonBuilder;
import java.io.Reader;
import java.util.ArrayList;
public class MainActivity extends Activity {
ProgressDialog progressDialog;
TextView txtSubject;
TextView txtAuthor;
TextView txtPrice;
TextView txtTopicsList;
Beansubject beanSubject;
StringBuffer topicList;
public void Json() {
new AsyncTask<Void,Void,Void>(){
#Override
protected void onPreExecute() {
super.onPreExecute();
ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setCancelable(false);
progressDialog.setMessage("Loading...");
progressDialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
Reader reader=API.getData("http://beta.json-generator.com/api/json/get/OkS85Le");
beanSubject = new GsonBuilder().create().fromJson(reader, Beansubject.class);
Log.e("Subject: ", beanSubject.getSubject() + "");
Log.e("Author: ", beanSubject.getAuthor() + "");
Log.e("Price: ", beanSubject.getPrice() + "");
ArrayList<BeanTopic> topicArrayList = beanSubject.getBeanTopics();
topicList = new StringBuffer();
for(BeanTopic topic: topicArrayList){
Log.e("topic title: ",topic.getTitle()+"");
topicList.append("* " + topic.getTitle()+"\n");
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
txtSubject.setText("Subject: " + beanSubject.getSubject());
txtPrice.setText("price: "+beanSubject.getPrice());
txtAuthor.setText("Author: "+beanSubject.getAuthor());
txtTopicsList.setText("Topics: "+"\n" + topicList);
}
}.execute();
}
}
The error is that I'm not sure how to create the objects that are in the tutorial in the last part for the activity class.
For the parts I did not understand in this last part of the tutorial where objects are being created which are possibly linked and possibly not to other classes I took random guesses for what they are.
I even made some stuff static in the other classes and removed "this." to get something to work. Please help me understand that last part of the tutorial so I could understand fully how to do this simple task. Thanks.
Here is the link to this simple tutorial:
http://www.nkdroid.com/2014/11/json-object-parsing-using-url-in-android.html
Okay, so these are my unknown variables: MyActivity.this, progressdialog, txtpostlist, postlist, beanpostarraylist. I am using a different tutorial now -> more basic. So I'm not sure why the tutorial is so vague with creating the MainActivity Class. What is missing? http://nkdroid.com/2014/11/json-parsing-using-gson-in-android.html
May help to look at the data being provided by API call.
paste result belo to http://json.parser.online.fr/
curl -v http://beta.json-generator.com/api/json/get/OkS85Le
{"topics": [{"title": "how to add fontawesome icons in android example"},
{"title": "how to parse json parsing using gson library"},
{"title": "how to store arraylist in sharedpreferences"}],
"auther": "nirav kalola",
"price": "free",
"subject": "Android Application Development Tutorial"}
So , the 3 "title" elements in the JSON wind up in UI because of the following :
beanSubject = new GsonBuilder().create().fromJson(reader, Beansubject.class);
ArrayList<BeanTopic> topicArrayList = beanSubject.getBeanTopics();
for(BeanTopic topic: topicArrayList){
topicList.append("* " + topic.getTitle()+"\n");
}
txtTopicsList.setText("Topics: "+"\n" + topicList);
code gets data
MVC model/collection objs created from JSON Array
UI list set from collection obj
see here for more on Adapters getting data from the collection Object holders.
You would need to create a layout that have some TextView components with the corresping ids. So create one xml file with some textviews with the proper ids. Then override the onCreate method, and call the JSON method:
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.id.my_layout);
txtSubject = (TextView) findViewById(R.id.txtSubject);
...
Json();
}
If something is unclear, I recommend you to read a basic android tutorial (the one from the official site is great).

Sonar plugin, how to save violations

I'm developing a sonar plugin to analyze TrueScript code using tslint.
I downloaded exampled plugin from [github.com/SonarSource/sonar-examples] and edited ExampleSensor.java [github.com/SonarSource/sonar-examples/tree/master/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch]. Now my sensor looks as in this file
package com.mycompany.sonar.reference.batch;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collection;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.Violation;
import pl.sollers.utils.FileSearcher;
public class ExampleSensor implements Sensor {
private static final Logger LOG = LoggerFactory.getLogger(ExampleSensor.class);
private Settings settings;
/**
* Use of IoC to get Settings
*/
public ExampleSensor(Settings settings) {
this.settings = settings;
}
public boolean shouldExecuteOnProject(Project project) {
// This sensor is executed only for ts project type
return project.getLanguageKey().equals("js");
}
public void analyse(Project project, SensorContext sensorContext) {
// getting all files for analyzing
Collection<File> files = FileSearcher.getByExtensionRecursively("ts");
Process tslintProces;
JSONParser jsonParser = new JSONParser();
JSONArray warnings;
Object jsonObj;
for (File file : files) {
try {
// run tslint process and analyze file
tslintProces = new ProcessBuilder("tslint.cmd", "-c", "./tslint.json", "-t",
"json", "-f", file.getCanonicalPath()).start();
// copy tslint output
StringWriter writer = new StringWriter();
IOUtils.copy(tslintProces.getInputStream(), writer, "UTF-8");
String json = writer.toString();
// parse output and extract violation message, ruleName, line
jsonObj = jsonParser.parse(json);
if (jsonObj instanceof JSONArray) {
warnings = (JSONArray) (jsonObj);
} else {
throw new Exception("Oczekiwano obiektu klasy JSONArray");
}
for (int i = 0; i < warnings.size(); i++) {
JSONObject warning = (JSONObject) warnings.get(i);
String message = (String) warning.get("failure");
String ruleName = (String) warning.get("ruleName");
JSONObject position = (JSONObject) warning.get("startPosition");
Long line = (Long) position.get("line");
// nie widzę pola w Sonarze aby użyć numeru znaku w linii
Long character = (Long) position.get("character");
// HELP! I DO NOT KNOW HOW TO STORE VIOLATION IN SONAR
// FOLLOWING LINES DOES NOT WORK
// Rule rule = Rule.create("repositoryKey",
String.format("%s-%s", "key", ruleName), ruleName);
// org.sonar.api.resources.File resource = new org.sonar.api.resources.File(file
.getParentFile().getCanonicalPath(), file.getName());
// Violation violation = Violation.create(rule, resource);
// violation.setLineId(line.intValue());
// violation.setMessage(message);
// sensorContext.saveViolation(violation);
}
} catch (IOException e) {
LOG.error(e.getMessage());
e.printStackTrace();
} catch (ParseException e) {
LOG.error(e.getMessage());
e.printStackTrace();
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
}
#Override
public String toString() {
return getClass().getSimpleName();
}
}
I have a problem in saving violations in Sonar database. This part of code should be in lines 80-90. Could anyone help me to store violations.
You should use Issueable rather than Violations (because it's deprecated and will be removed in 4.3).
import org.sonar.api.component.ResourcePerspectives;
public class MySensor extends Sensor {
private final ResourcePerspectives perspectives;
public MySensor(ResourcePerspectives p) {
this.perspectives = p;
}
public void analyse(Project project, SensorContext context) {
Resource myResource; // to be set
Issuable issuable = perspectives.as(Issuable.class, myResource);
if (issuable != null) {
// can be used
Issue issue = issuable.newIssueBuilder()
.setRuleKey(RuleKey.of("pmd", "AvoidArrayLoops")
.setLine(10)
.build();
issuable.addIssue(issue);
}
}
}

Covert a code to class

Can any one help me to learn how to convert a code to a class so I can use it every where?
for example I have this code
How can I convert it to a separate class and use it in my diffrent activities?
I am new with java and really have problem with this..Thanks for your helps
public String getInformationData(String mySQL){
String information_text=null;
try{
db = SQLiteDatabase.openDatabase(ClubCP.DbPath,null,SQLiteDatabase.CREATE_IF_NECESSARY);
Cursor information = mDb.rawQuery(mySQL,null);
int information1 = information.getColumnIndex("description");
while (information.moveToNext()) {
String columns = (String) information.getString(information1);
information_text = "<head><style>#font-face {font-family: 'verdana';src: url('file://"+ ClubCP.SDcardPath+ "Homa.ttf');}body {font-family: 'verdana';color:#ffffff;font-size:18px;padding:10px 10px 0 10px;}</style></head>"+"<html Content-Type: text/html charset=UTF-8;dir=\"rtl\"><body>"
+ "<p dir=\"rtl\" align=\"justify\">"
+ columns
+ "</p> "
+ "</body></html>";
}
} catch (Exception e) {
Toast.makeText(callingActivity, e.getMessage(), 1).show();
}
return information_text;
}
Finally I created my class..I added another method to it but when I call it I get FC ..Where is my mistake?
package co.tosca.persianpoem;
import java.io.File;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
public class persian_poem_class {
private Context c = null;
private SQLiteDatabase Db=null;
private Activity callingActivity;
//private Resources res =null ;
public persian_poem_class(Context c,Activity a)
{
// Constructor
this.c = c;
Db = SQLiteDatabase.openDatabase(ClubCP.DbPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
callingActivity=a;
}
public String getInformationData(String mySQL)
{
String information_text = null;
try
{
Cursor information = Db.rawQuery(mySQL,null);
int information1 = information.getColumnIndex("description");
while (information.moveToNext())
{
String columns = (String) information.getString(information1);
information_text = "<head><style>#font-face {font-family: 'verdana';src: url('file://"+ ClubCP.SDcardPath+ "Homa.ttf');}body {font-family: 'verdana';color:#ffffff;font-size:18px;padding:10px 10px 0 10px;}</style></head>"+"<html Content-Type: text/html charset=UTF-8;dir=\"rtl\"><body>"
+ "<p dir=\"rtl\" align=\"justify\">"
+ columns
+ "</p> "
+ "</body></html>";
}
}
catch (Exception e)
{
Toast.makeText(c, e.getMessage(), Toast.LENGTH_SHORT).show();
}
return information_text;
}
public void Change_header(View v,String id){
String path = ClubCP.SDcardPath + "/temp/"+id+"-header.jpg";
Log.i("view binder", path);
File imgFile = new File(path);
ImageView img=(ImageView)v;
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
img.setImageBitmap(myBitmap);
}
else {
img.setImageDrawable(callingActivity.getDrawable(R.drawable.music_album_header_vinyl));
}
}
public Cursor getData(String mySQL){
Cursor c = Db.rawQuery(mySQL, null);
return c;
}
public void closeMyDb()
{
if (Db != null)
Db.close();
else
throw new NullPointerException("No database selected!");
}
}
I call secound method by this code
persian_poem_class main = new persian_poem_class(Book_list.this);
ImageView header=(ImageView)findViewById(R.id.img_header_book_list_activity);
main.Change_header(header, Peot_ID_for_db);
Again thanks for your time..
I fixed my class but now I have another problem with Change_header method..I get this error for getDrawable(R.drawable.music_album_header_vinyl) "getdrawable is undifined" I searched and I found problem is with scope but Cant fix it..I tried c.getDrawable but still have problementer code here
Okay I made a simple class according your request but some section of your code is unclear to me like ClubCP.DbPath or ClubCP.SDcardPath that I think these are static variables.
Anyway to use this class you need to make new instance from myClass:
myClass mMyClass = new myClass(youractivity.this);
mMyClass.getInformationData("your query");
mMyClass.closeMyDb() // To close your current database
Edited as per comment:
import java.io.File;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
public class myClass
{
private Context c = null;
private SQLiteDatabase mDb;
public myClass(Context c)
{
// Constructor
this.c = c;
mDb = SQLiteDatabase.openDatabase(ClubCP.DbPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
}
public String getInformationData(String mySQL)
{
String information_text = null;
try
{
Cursor information = mDb.rawQuery(mySQL,null);
int information1 = information.getColumnIndex("description");
while (information.moveToNext())
{
String columns = (String) information.getString(information1);
information_text = "<head><style>#font-face {font-family: 'verdana';src: url('file://"+ ClubCP.SDcardPath+ "Homa.ttf');}body {font-family: 'verdana';color:#ffffff;font-size:18px;padding:10px 10px 0 10px;}</style></head>"+"<html Content-Type: text/html charset=UTF-8;dir=\"rtl\"><body>"
+ "<p dir=\"rtl\" align=\"justify\">"
+ columns
+ "</p> "
+ "</body></html>";
}
}
catch (Exception e)
{
Toast.makeText(c, e.getMessage(), Toast.LENGTH_SHORT).show();
}
return information_text;
}
public void Change_header(View v, String id)
{
String path = ClubCP.SDcardPath + "/temp/"+id+"-header.jpg";
Log.i("view binder", path);
File imgFile = new File(path);
ImageView img = (ImageView) v;
if(imgFile.exists())
{
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
img.setImageBitmap(myBitmap);
}
else
img.setImageDrawable(c.getResources().getDrawable(R.drawable.music_album_header_vinyl));
}
public void closeMyDb()
{
if (mDb != null)
mDb.close();
else
throw new NullPointerException("No database selected!");
}
}
First, create a new class with a name that is descriptive of what it does (i.e. replace myClass with the name). Then, you create a constructor for this class by calling public myClass() WITHOUT a return type (this is how Java identifies it as a constructor. The constructor is what gets called every time the class runs, so simply paste your code in the body of the constructor, and it will get called every time you create a new object of the class.
Class myClass {
...
public myClass(){
public String getInformationData(String mySQL){
String information_text=null;
try{
db = SQLiteDatabase.openDatabase ...
... rest of code...
return information_text;
}
}
}
Welcome to object-oriented programming :)
Simple create a new class by right clicking on your src folder and clicking create new class.
Once you've gone the through the process of naming your class, go and paste your current code into that class, which would be your public String getInformationData(String mySQL) method.
Once this has been done, create a reference to this class, be creating an object of this class in every class/activity you want to call String getInformationData(String mySQL) from.
YourClass foo = new YourClass();
foo.getInformationData(string);
I hope this helps.

lang.ClassCastException: java.lang.Integer android xml rpc

i'm ahaving an issue while trying to make an xml rpc request. my serive crashes whith the logcat saying lang.ClassCastException: java.lang.Integer at the line 35 of my code which coresponds to the client call * >>> text = (String) client.call<<<<<*.
package tfe.rma.ciss.be;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.util.Enumeration;
import org.xmlrpc.android.XMLRPCClient;
import org.xmlrpc.android.XMLRPCException;
import android.app.Service;
import android.content.Intent;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.IBinder;
import android.widget.Toast;
public class Addviewer extends Service {
private XMLRPCClient client;
private URI uri;
String text="", IpAdress;
#Override
public void onCreate(){}
public void onStart(Intent intent, int StartId){
uri = URI.create("http://fuseng.elte.rma.ac.be:8080/RPC2");
client = new XMLRPCClient(uri);
getLocalIpAddress();
if (!IpAdress.equals("R.A.S")){
try {
text = (String) client.call("mission.addViewer",IpAdress+ ":" + 8214, "newImage");
} catch (XMLRPCException e) {
// TODO Auto-generated catch block
e.printStackTrace();
text= "erro in adding viewer with the exception:" + e + "/n" + "try again later";
}
Toast.makeText(this,"suscribtion to the viewer with the result " + text, Toast.LENGTH_SHORT).show(); }
else {
Toast.makeText(this,"No network avalaible right now" + "/n" + "try again later", Toast.LENGTH_SHORT).show();
}
}
public String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
IpAdress= inetAddress.getHostAddress().toString();
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
IpAdress="R.A.S";
}
return null;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
so i changed the sparametr newImage by an integer (i.e 214) and then it (the service) works fine except that the server replies me that it is expecting a string at the second parameter (i was already aware of it)... please help
The problem is that client.call(...) is returning an Integer, not a String. For example, it might be returning 20 (or rather, Integer.valueOf(20)), whereas your code expects it to be returning something like "20". If your goal is to convert its return value of 20 to "20" for display purposes, then you should change this:
text = (String) client.call("mission.addViewer",IpAdress+ ":" + 8214, "newImage");
to this:
text = String.valueOf(client.call("mission.addViewer",IpAdress+ ":" + 8214, "newImage"));

How to read MP3 file tags

I want to have a program that reads metadata from an MP3 file. My program should also able to edit these metadata. What can I do?
I got to search out for some open source code. But they have code; but not simplified idea for my job they are going to do.
When I read further I found the metadata is stored in the MP3 file itself. But I am yet not able to make a full idea of my baby program.
Any help will be appreciated; with a program or very idea (like an algorithm). :)
The last 128 bytes of a mp3 file contains meta data about the mp3 file., You can write a program to read the last 128 bytes...
UPDATE:
ID3v1 Implementation
The Information is stored in the last 128 bytes of an MP3. The Tag
has got the following fields, and the offsets given here, are from
0-127.
Field Length Offsets
Tag 3 0-2
Songname 30 3-32
Artist 30 33-62
Album 30 63-92
Year 4 93-96
Comment 30 97-126
Genre 1 127
WARINING- This is just an ugly way of getting metadata and it might not actually be there because the world has moved to id3v2. id3v1 is actually obsolete. Id3v2 is more complex than this, so ideally you should use existing libraries to read id3v2 data from mp3s . Just putting this out there.
You can use apache tika Java API for meta-data parsing from MP3 such as title, album, genre, duraion, composer, artist and etc.. required jars are tika-parsers-1.4, tika-core-1.4.
Sample Program:
package com.parse.mp3;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.mp3.Mp3Parser;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class AudioParser {
/**
* #param args
*/
public static void main(String[] args) {
String fileLocation = "G:/asas/album/song.mp3";
try {
InputStream input = new FileInputStream(new File(fileLocation));
ContentHandler handler = new DefaultHandler();
Metadata metadata = new Metadata();
Parser parser = new Mp3Parser();
ParseContext parseCtx = new ParseContext();
parser.parse(input, handler, metadata, parseCtx);
input.close();
// List all metadata
String[] metadataNames = metadata.names();
for(String name : metadataNames){
System.out.println(name + ": " + metadata.get(name));
}
// Retrieve the necessary info from metadata
// Names - title, xmpDM:artist etc. - mentioned below may differ based
System.out.println("----------------------------------------------");
System.out.println("Title: " + metadata.get("title"));
System.out.println("Artists: " + metadata.get("xmpDM:artist"));
System.out.println("Composer : "+metadata.get("xmpDM:composer"));
System.out.println("Genre : "+metadata.get("xmpDM:genre"));
System.out.println("Album : "+metadata.get("xmpDM:album"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (TikaException e) {
e.printStackTrace();
}
}
}
For J2ME(which is what I was struggling with), here's the code that worked for me..
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.lcdui.*;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import javax.microedition.media.control.MetaDataControl;
import javax.microedition.midlet.MIDlet;
public class MetaDataControlMIDlet extends MIDlet implements CommandListener {
private Display display = null;
private List list = new List("Message", List.IMPLICIT);
private Command exitCommand = new Command("Exit", Command.EXIT, 1);
private Alert alert = new Alert("Message");
private Player player = null;
public MetaDataControlMIDlet() {
display = Display.getDisplay(this);
alert.addCommand(exitCommand);
alert.setCommandListener(this);
list.addCommand(exitCommand);
list.setCommandListener(this);
//display.setCurrent(list);
}
public void startApp() {
try {
FileConnection connection = (FileConnection) Connector.open("file:///e:/breathe.mp3");
InputStream is = null;
is = connection.openInputStream();
player = Manager.createPlayer(is, "audio/mp3");
player.prefetch();
player.realize();
} catch (Exception e) {
alert.setString(e.getMessage());
display.setCurrent(alert);
e.printStackTrace();
}
if (player != null) {
MetaDataControl mControl = (MetaDataControl) player.getControl("javax.microedition.media.control.MetaDataControl");
if (mControl == null) {
alert.setString("No Meta Information");
display.setCurrent(alert);
} else {
String[] keys = mControl.getKeys();
for (int i = 0; i < keys.length; i++) {
list.append(keys[i] + " -- " + mControl.getKeyValue(keys[i]), null);
}
display.setCurrent(list);
}
}
}
public void commandAction(Command cmd, Displayable disp) {
if (cmd == exitCommand) {
notifyDestroyed();
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}

Categories