unfotunatly the application stopped [duplicate] - android

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
detail of list item in another screen
When I select an item I want the application to navigate to the second activity and take a value of selected item and the related link to the TextView which exists in the second activity. The code should work but when I run it the emulator gives me a message saying "Unfortunately the application stopped". I don't know what to do to make it work?
public class LastActivity extends ListActivity {
/** Called when the activity is first created. */
static List<String> links;
List<String> names;
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
String link=links.get(position);
Intent intent = new Intent(getApplicationContext(),Details.class);
intent.putExtra("name",names.get(position));
intent.putExtra("url",link);
Log.e("n",names.get(position)+"."+ link );
startActivity(intent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
links=new ArrayList<String>();
names=new ArrayList<String>();
try{
URL url=new URL(webservice);
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(getInputStream(url), "UTF_8");
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, etc..
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("item")) {
insideItem = true;
} else if (xpp.getName().equalsIgnoreCase("Name")) {
if (insideItem)
names.add(xpp.nextText()); //extract the headline
} else if (xpp.getName().equalsIgnoreCase("url")) {
if (insideItem)
links.add(xpp.nextText()); //extract the link of article
}
}else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
insideItem=false;
}
eventType = xpp.next(); //move to next element
}
}catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, names);
setListAdapter(adapter);
}
private InputStream getInputStream(URL url) {
// TODO Auto-generated method stub
try {
return url.openConnection().getInputStream();
} catch (IOException e) {
return null;
}
}
}
//second class or acticvites
public class Details extends LastActivity{
LastActivity last=new LastActivity();
TextView tv;
TextView url;
String read;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
tv=(TextView) findViewById(R.id.text);
url=(TextView) findViewById(R.id.link);
Intent intent=getIntent();
// receiving data
String name = intent.getStringExtra("name");
String path=intent.getStringExtra("links");
Log.e("Second Screen", name + "." + path);
tv.setText(name);
url.setText(path);
}

I think the problem is with passing putExtra values in the intents. Check your first Activity, you have used the key as "url", but in the details Activity you are using "links" as the key. So you are getting null Pointer Exception. Change it properly.
intent.putExtra("name",names.get(position));
intent.putExtra("url",link);
in Details Activity,
String name = intent.getStringExtra("name");
String path=intent.getStringExtra("url");
instead of,
String path=intent.getStringExtra("links");
In your First Activity you have exntended ListActivty, try to replace it with Activity alone.
Or change your ListView id to #android:list in your xml file.
For more info, look at this question , "Stopped Unexpectedly" tried 10000 times to fix
And also check this for more idea,
Your content must have a ListView whose id attribute is 'android.R.id.list

Related

Android SQLiteOpenHelper time-consuming onCreate, need progress bar on first run

The first time my app runs it creates a database in which it loads 6,000 rows from a file in /res/raw. I can't do this asynchronously as the app depends on it entirely. It runs rapidly on my phone - a Moto X - but it's really slow in all my emulators and I'm concerned it could be a bit slower on slower devices thus making the user stare at a blank screen for a few seconds before the app does anything.
Is there a way to put a progress bar while running the overrided SQLiteOpenHelper's onCreate() methood and have it update the progress bar with how far along it is, with a message saying something like "Initializing data for first use!"?
I solved this problem by starting an AsyncTask in onCreate and then only loading the layout at the end of the 'AsyncTask` (or if the data had previously been loaded). It works beautifully as a loading screen. I followed this tutorial http://www.41post.com/4588/programming/android-coding-a-loading-screen-part-1 (which explains the details more) then changed it a bit for my needs (such as loading a raw resource).
I should say that although it does it asynchronously because the main layout hasn't loaded the user has to wait for the loading to complete before he or she can continue, so hopefully that means it doing it asynchronously won't be a problem for you with the app depending on the database.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedPref = getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE);
dataAddedToDB = (sharedPref.getBoolean(PXS_RXS_UPDATE, false));
if (!dataAddedToDB) {
new LoadViewTask(this).execute();
} else {
setContentView(R.layout.activity_main);
}
}
In the AsyncTask it loads the database showing how far it has got and showing your message and then only goes on to show the layout at the end. (BTW, it is helpful to lock the screen orientation while doing this to stop it messing it up).
EDIT: publishProgress(counter); passes the value of where the task has got to to onProgressUpdate().
private class LoadViewTask extends AsyncTask<Void, Integer, Void> {
private Context context;
public LoadViewTask(Context context) {
this.context = context.getApplicationContext();
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setTitle("Loading...");
progressDialog.setMessage("Initializing data for first use!");
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(false);
// this counts how many line to be added to the database so it can later tell how far it has got.
final Resources resources2 = context.getResources();
InputStream inputStream2 = resources2.openRawResource(R.raw.rawherbaldata);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream2));
int lineCount = 0;
try {
String line;
while ((line = reader.readLine()) != null) {
lineCount++;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
progressDialog.setMax(lineCount);
progressDialog.setProgress(0);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
HerbalDatabaseOpenHelper mHerbalDbHelper = new HerbalDatabaseOpenHelper(MainActivity.this);
SQLiteDatabase db = mHerbalDbHelper.getWritableDatabase();
int counter = 0;
final Resources resources2 = context.getResources();
InputStream inputStream2 = resources2.openRawResource(R.raw.rawherbaldata);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream2));
db.beginTransaction();
try {
int lineNumber = 1;
String line;
while ((line = reader.readLine()) != null) {
// CODE FOR ENTERING LINE INTO DATABASE
// EDIT: the following keeps the task updated on where it has got to, passing the count to onProgressUpdate()
counter++;
publishProgress(counter);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
db.setTransactionSuccessful();
db.endTransaction();
db.close();
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
SharedPreferences sharedPref = getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE);
pxsRxsUpdate = true;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(PXS_RXS_UPDATE, pxsRxsUpdate);
editor.commit();
// initialize the View
setContentView(R.layout.activity_main);
}
}
You could use another intermediate activity which would show the progress dialog and then send you back to the main activity when done.
First you'll need a static method that a boolean if the DB has already been create.
Then inside of your activity's onCreate call the middleman if necessary:
DbHelper mDbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!DbHelper.isDbCreated()) {
Intent intent = new Intent(this, DbActivity.class);
startActivity(intent);
finish();
return;
}
// Do normal stuff like instantiating the helper and so on
mDbHelper = new DbHelper();
...
}
Then inside of this "middleman" activity show the ProgressDialog and create the database.
Once you're done, hide the dialog and go back to your main activity:
mProgress.dismiss();
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
return;
If your static method isDbCreated() is created properly, you won't reveal the MainActivity's content until the database is created.
EDIT:
Here's the method I use to check for the database. Perhaps it will help you.
public boolean isDbCreated() {
String sDatabasePath = context.getDatabasePath(DB_NAME).getPath();
SQLiteDatabase tmpDb = null;
if (mContext.getDatabasePath(DB_NAME).exists()) {
try {
tmpDb = SQLiteDatabase.openDatabase(sDatabasePath, null,
SQLiteDatabase.OPEN_READONLY);
tmpDb.close();
} catch (SQLiteException e) {
e.printStackTrace();
}
} else {
Log.e(TAG, "DB file doesn't exist.");
// If the parent dir doesn't exist, create it
File parentDir = new File(mContext.getDatabasePath(DB_NAME).getParent());
if (!parentDir.exists()) {
if (parentDir.mkdirs()) {
Log.d(TAG, "Successfully created the parent dir:" + parentDir.getName());
} else {
Log.e(TAG, "Failed to create the parent dir:" + parentDir.getName());
}
}
}
return (tmpDb != null);
}

How to get string value from string array in Android

I am trying to create an application that reads an NFC tag and checks the tag against strings in a string array and then sets the text on another activity. I have got it working so that it checks if the string exists and sets the text in the new activity, but I want to be able to specify which string I want it to check against within the array, because there will be multiple strings in the NFC tag that I want to then display in the new activity. I have tried this for it:
result == getResources().getString(R.string.test_dd)
Here is the relevant code:
String[] dd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dd = getResources().getStringArray(R.array.device_description);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
if(doesArrayContain(dd, result)) {
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(800);
Intent newIntent = new Intent(getApplicationContext(), TabsTest.class);
Bundle bundle1 = new Bundle();
bundle1.putString("key", result);
newIntent.putExtras(bundle1);
startActivity(newIntent);
Toast.makeText(getApplicationContext(), "NFC tag written successfully!", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), result + " is not in the device description!", Toast.LENGTH_SHORT).show();
}
}
}
EDIT:
Here is the method used and please can anyone help me with this problem:
public static boolean doesArrayContain(String[] array, String text) {
for (String element : array) {
if(element != null && element.equalsIgnoreCase(text)) {
return true;
}
}
return false;
}
For comparing equality of strings (and other objects) use the equals() method. == compares identity of objects (same string object).
Here is the solution that I found:
Create a new method:
public static boolean stringCaseInsensitive(String string, String result) {
if(string != null && string.equalsIgnoreCase(result)) {
return true;
}
return false;
}
And call it in like this:
if(stringCaseInsensitive(getResources().getString(R.string.test_dd), result))
{
Intent newIntent = new Intent(getApplicationContext(), TabsTest.class);
Bundle bundle1 = new Bundle();
bundle1.putString("key", result);
newIntent.putExtras(bundle1);
startActivity(newIntent);
Toast.makeText(getApplicationContext(), "NFC tag written successfully!", Toast.LENGTH_SHORT).show();
}
else{
}

Android xmlparsing and putting data in listview

I have two activity class of android. The main activity class contains xml parsing and i am trying to pass the data obtain from there to another activity class which is going to put it into listview of all the data. Below the is xml parsing main activity the problem is that, when I run the program it show nullpointer exception . I m stuck here can anyone help me where is the error . Thnx in advance
enter code here
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
try {
stringXmlContent = getEventsFromAnXML(this);
Intent i=new Intent(LocationSidActivity.this,FacebookData.class);
i.putStringArrayListExtra("language", stringXmlContent);
startActivity(i);
// myXmlContent.setText(stringXmlContent);
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private ArrayList<String> getEventsFromAnXML(Activity activity)
throws XmlPullParserException, IOException {
ArrayList<String> al = new ArrayList<String>();
Resources res = activity.getResources();
XmlResourceParser xpp = res.getXml(R.xml.myxml);
xpp.next();
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
al.add(xpp.getName());
} else if (eventType == XmlPullParser.START_TAG) {
//if ((xpp.getName()).compareTo("id") != 0) {
al.add(xpp.getName());
//} else {
//eventType = xpp.next();
}
else if (eventType == XmlPullParser.TEXT) {
al.add(xpp.getText());
}
eventType = xpp.next();
}
return al;
}
}
The lines in your parser method getEventsFromAnXML:
if (eventType == XmlPullParser.START_DOCUMENT)
{
al.add(xpp.getName());
}
may end up in a NullPointerException, because there is nothing read yet, and a null value will be added as the first member of your ArrayList.
The XmlPullParser.START_DOCUMENT in API Docs:
Signalize that parser is at the very beginning of the document and
nothing was read yet. This event type can only be observed by calling
getEvent() before the first call to next(), nextToken, or nextTag()).
Also, if the getEventsFromAnXML method is in your Activity class, you should remove the parameter, and simply use this. It is never a good practice to share a Context, it will most often end up in leaks.

Memory-leak android using arrays and files

I'm developing a dictionary using *.txt files in /raw directory, also I have a history (current 18 entries).
Every OnResume() I'm getting history entries from file on SDCard and filling ListArray's than use ArrayAdapter to fill a ListView.
I can't understand why I have a big memory leak (every onResume() adds about 4-6 MB to the memory). Please help me.
Here is my code:
public class SecondTab extends Activity {
ListView lv1;
ArrayList <String> ArrayHist = new ArrayList <String>();
ArrayList <String> ArrayHistMin = new ArrayList <String>();
BufferedReader Buffer;
InputStream file;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hist);
SetContent();
if (ru.andr.dictu.FirstTab.myErrorInHist)
{
Toast.makeText(this, getString(R.string.err_hist), Toast.LENGTH_LONG).show();
}
}
public void SetContent()
{
//show History entries
//trying to solve memory leak
try
{
ArrayHist.clear();
ArrayHistMin.clear();
}
catch (Exception e){}
ArrayHist=null;
ArrayHistMin=null;
ArrayHist = new ArrayList <String>();
ArrayHistMin = new ArrayList <String>();
Buffer=null;
file=null;
if (ru.andr.dictu.FirstTab.myErrorInHist!=true)
{
//filling arrays
try {
file = new FileInputStream(ru.andr.dictu.history_func.File_hist()); //getting name of file from common store
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Buffer = new BufferedReader(new InputStreamReader(file));
try {
String Str;
int counter_hist_content = 0;
while ( (Str = Buffer.readLine()) != null){ //reading from history file
String myTrimStr = Str.trim();
ArrayHistMin.add(myTrimStr.substring(0, myTrimStr.indexOf(";;")).intern()); //main word
ArrayHist.add(myTrimStr.substring(myTrimStr.indexOf(";;")+2).intern()); //ususaly translate
if (counter_hist_content==50) break;//needs only 50 entries
counter_hist_content++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try
{
//closing files, buffers
file.reset();
file.close();
Buffer.reset();
Buffer.close();
}catch (Exception e) {}
}
lv1 = (ListView)findViewById(R.id.history);
lv1.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item_hist, ArrayHistMin));
lv1.setTextFilterEnabled(true);
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
changeClass (position , ArrayHist.get(position));
}
});
lv1.setOnItemLongClickListener(new OnItemLongClickListener(){
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
ru.andr.dictu.myspeak.text=null;
ru.andr.dictu.myspeak.text=ArrayHistMin.get(arg2);
if (ru.andr.dictu.myspeak.text.indexOf("[")!=-1)
ru.andr.dictu.myspeak.text=ru.andr.dictu.myspeak.text.substring(0,ru.andr.dictu.myspeak.text.indexOf("[")).intern();
speakClass();
return true;
}
});
}
public void speakClass() {
Intent intent = new Intent();
intent.setClass(this, myspeak.class);
startActivity(intent);
}
public void changeClass(int position, String extArray) {
Intent intent = new Intent();
intent.setClass(this, List.class);
intent.putExtra(List.results, extArray.toString().intern());
startActivity(intent);
getParent().overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
}
#Override protected void onPause() {super.onPause(); }
#Override
protected void onResume()
{
super.onResume();
SetContent();
}
My guess is the new InputStreamReader(file) is being leaked. You need to close this reader.
Though if this does not solve the problem, dump the hprof data and check using MAT tool in eclipse. You can point out which class is taking maximum heap.
Edit: You can dump hprof in DDMS view. It is one of the buttons right above where processes are displayed

Android - Progress Dialog

I'm a having a problem. I want to make a progress dialog while my app download some news from a feed.
This is my code at the moment:
public class NyhedActivity extends Activity {
String streamTitle = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.nyheder);
TextView result = (TextView)findViewById(R.id.result);
try {
URL rssUrl = new URL("http://rss.tv2sport.dk/rss/*/*/*/248/*/*");
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
XMLReader myXMLReader = mySAXParser.getXMLReader();
RSSHandler myRSSHandler = new RSSHandler();
myXMLReader.setContentHandler(myRSSHandler);
InputSource myInputSource = new InputSource(rssUrl.openStream());
myXMLReader.parse(myInputSource);
result.setText(streamTitle);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result.setText("Cannot connect RSS!");
}
}
private class RSSHandler extends DefaultHandler
{
final int stateUnknown = 0;
final int stateTitle = 1;
int state = stateUnknown;
int numberOfTitle = 0;
String strTitle = "";
String strElement = "";
#Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
strTitle = "Nyheder fra ";
}
#Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
strTitle += "";
streamTitle = "" + strTitle;
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("title"))
{
state = stateTitle;
strElement = "";
numberOfTitle++;
}
else
{
state = stateUnknown;
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("title"))
{
strTitle += strElement + "\n"+"\n";
}
state = stateUnknown;
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String strCharacters = new String(ch, start, length);
if (state == stateTitle)
{
strElement += strCharacters;
}
}
}
}
I can't figure out how to use the progress dialog. Is it possible for anyone to show my where to define the progressdialog and least but not most how to implement it.
I've looked a lot of places, but everyone seems to do it different ways, and I can't get any of them to work :(
I've even tried to make a fake one which runs on sleep, but I can't figure out what I'm doing wrong.
My preferred way:
class MyActivity extends Activity{
final static int PROGRESS_DIALOG = 1;
ProgressDialog dialog;
#Override
protected Dialog onCreateDialog(int id){
switch(id){
case PROGRESS_DIALOG:
dialog = new ProgressDialog(this);
dialog.setMessage("Whatever you want to tell them.");
dialog.setIndeterminate(true);
dialog.setCancelable(true); // if you want people to be able to cancel the download
dialog.setOnCancelListener(new DialogInterface.OnCancelListener(){
#Override
public void onCancel(DialogInterface dialog)
{
**** cleanup. Not needed if not cancelable ****
}});
return dialog;
default:
return null;
}
}
When you want it to appear, you can do showDialog(PROGRESS_DIALOG) and when you want it to go away you can do dialog.dismiss().
Don't do any long-running stuff like network IO in the UI thread (that's what calls your onCreate()), Android will force close your app. Use an AsyncTask instead, check out the linked javadoc for an example.
Create and show your progress dialog in onPreExecute() and keep a reference to it in a field
Update progress by calling publishProgress() from your doInBackground() and handle that in onProgressUpdate(), e.g. like the example linked above
Close your progress dialog and update your UI (text fields, etc.) in onPostExecute()
To create the dialog in onPreExecute(), pass a Context to your AsyncTask constructor, e.g. your activity this and store it in a field.
If you want your data to survive orientation changes or persist across activity restarts, let your AsyncTask write your parsed data into a SQLite database and then display it only the database contents in your activity.
As for the actual "showing a progress dialog" part, use one of its static factory methods show(...):
ProgressDialog dialog = ProgressDialog.show(
this, // a context, e.g. your activity
"Downloading...", // title
"Downloading RSS feed.", // message
);
This will create and show a dialog in one step.

Categories

Resources