I want to add a item to the child Today from another activity to the ExpandableListView. The activity where I want to add it is named LocHistory, here is a the code to add something to the list:
Code:
static void addListData(final Context context) {
List<NewsItem> list = listDataChild.get("Today");
NewsItem newsData = new NewsItem();
newsData = new NewsItem();
newsData.setHeadline("11.11111, 1.1111");
newsData.setSpeed("1.11KM/H");
newsData.setDirection("111");
newsData.setDate("11-1-1111 11:11:11");
list.add(0, newsData);
listDataChild.put("Today", list);
}
This is working when I have call the function in the same class (LocHistory). But when I call it in MainActivity like this:
Code:
public class MainActivity extends Activity {
Button button2;
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button2 = (Button) this.findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
LocHistory.addListData(getBaseContext());
}
});
}
}
Then there is nothing added to the list. Is it possible to add a item from another activity to ExpandableListView? I want if there's something added that the class LocHistory is not going to open, so I think startActivity with a intent is not a option here (but i'm not sure).
(The java sources can be found here:
MainActivity.java pastebin.com/YWyfznwv
LocHistory.java - pastebin.com/XJ274C61
NewsItem.java - pastebin.com/uhmXbnhJ
ExpandableListAdapter.java - pastebin.com/5jPV8daz)
Alwaysup said:
I want to add a item to the child Today from another activity to the ExpandableListView. The activity where I want to add it is named LocHistory, here is a the code to add something to the list:
Code:
static void addListData(final Context context) {
List<NewsItem> list = listDataChild.get("Today");
NewsItem newsData = new NewsItem();
newsData = new NewsItem();
newsData.setHeadline("11.11111, 1.1111");
newsData.setSpeed("1.11KM/H");
newsData.setDirection("111");
newsData.setDate("11-1-1111 11:11:11");
list.add(0, newsData);
listDataChild.put("Today", list);
}
This is working when I have call the function in the same class (LocHistory). But when I call it in MainActivity like this:
Code:
public class MainActivity extends Activity {
Button button2;
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button2 = (Button) this.findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
LocHistory.addListData(getBaseContext());
}
});
}
}
Then there is nothing added to the list. Is it possible to add a item from another activity to ExpandableListView? I want if there's something added that the class LocHistory is not going to open, so I think startActivity with a intent is not a option here (but i'm not sure).
(The java sources can be found here:
MainActivity.java pastebin.com/YWyfznwv
LocHistory.java - pastebin.com/XJ274C61
NewsItem.java - pastebin.com/uhmXbnhJ
ExpandableListAdapter.java - pastebin.com/5jPV8daz)
Click to expand...
Click to collapse
In Android, try to use as few static variables and methods as possible. To get a non-static access to the method, make it public and get an instance of the list adapter in the activity (via list.getAdapter () or create a new one and set the listAdapter in the expListView).
If you really want to access it through 2 activities, I'm sorry, there's no way of doing this directly. You'd have to save it in a file or your SharedPreferences and get the items once you get to the other activity.
And also, why do you need that context object in addListData()? That could lead to memory leak...
In this thread you can find a solution. There is a library called EventBus which they used. Read it completely (just 2 pages).
http://forum.xda-developers.com/showthread.php?t=2332069
By the way,
When I log the listDataChild in the function addListData then it seems that the item is added under the child Today (the logging is only working when I first open the class LocHistory and close it). The prepareListData function is called in the onCreate method. Is it maybe that function overrides the listDataChild that is created by the function addListData?
SimplicityApks said:
In Android, try to use as few static variables and methods as possible. To get a non-static access to the method, make it public and get an instance of the list adapter in the activity (via list.getAdapter () or create a new one and set the listAdapter in the expListView).
If you really want to access it through 2 activities, I'm sorry, there's no way of doing this directly. You'd have to save it in a file or your SharedPreferences and get the items once you get to the other activity.
And also, why do you need that context object in addListData()? That could lead to memory leak...
Click to expand...
Click to collapse
Sorry for the context object in addListData() is was doing some test with SharedPreferences and then I've to use the context object (I've removed now). Can you call list.getAdapter() from another activity?
nikwen said:
In this thread you can find a solution. There is a library called EventBus which they used. Read it completely (just 2 pages).
http://forum.xda-developers.com/showthread.php?t=2332069
Click to expand...
Click to collapse
Thanks for the link, I will study this. Altough I not prefer to include an other library
Alwaysup said:
By the way,
When I log the listDataChild in the function addListData then it seems that the item is added under the child Today (the logging is only working when I first open the class LocHistory and close it). The prepareListData function is called in the onCreate method. Is it maybe that function overrides the listDataChild that is created by the function addListData?
Sorry for the context object in addListData() is was doing some test with SharedPreferences and then I've to use the context object (I've removed now). Can you call list.getAdapter() from another activity?
Thanks for the link, I will study this. Altough I not prefer to include an other library
Click to expand...
Click to collapse
The event Bus is a cool library, but the question is whether it's worth including a lib to do just that. You can usually try to combine both activities into one with Fragments and a ViewPager.
The list can only be accessed in its own activity, so list.getAdapter() won't work. But u can still write the data to a file on the SD card or use a SQLite database (or SharedPreferences for non-objects).
I found out that what's probably better is to use less activities or use SharedPreferences wherever it's possible since it's cleaner and faster.
Had a similar problem a while ago (but I needed to pass data to a starting activity) and solved it using a Bundle (via Intent), but then realized the app is much nicer combining both activities...
SimplicityApks said:
The event Bus is a cool library, but the question is whether it's worth including a lib to do just that. You can usually try to combine both activities into one with Fragments and a ViewPager.
The list can only be accessed in its own activity, so list.getAdapter() won't work. But u can still write the data to a file on the SD card or use a SQLite database (or SharedPreferences for non-objects).
I found out that what's probably better is to use less activities or use SharedPreferences wherever it's possible since it's cleaner and faster.
Had a similar problem a while ago (but I needed to pass data to a starting activity) and solved it using a Bundle (via Intent), but then realized the app is much nicer combining both activities...
Click to expand...
Click to collapse
I agree. The less Activities, the better the app. (At least until all Activities are crowded. )
As you guys pointed out, I'm now using SharedPreferences. I'm using this code:
Code:
private static int startOf(String day) {
Date date = new Date(System.currentTimeMillis());
//TimeZone tzGMT = TimeZone.getTimeZone("GMT");
Calendar cal = Calendar.getInstance();
//cal.setTimeZone(tzGMT);
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
// change to seconds
long ltimeM = cal.getTimeInMillis();
int iTimeStamp = 0;
if (day == "today") {
iTimeStamp = (int) (ltimeM / 1000);
} else if (day == "yesterday") {
iTimeStamp = (int) ((ltimeM / 1000) - 86400);
}
cal.set(Calendar.HOUR_OF_DAY, cal.getActualMinimum(Calendar.HOUR_OF_DAY));
cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE));
cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND));
//return Integer.toString(iTimeStamp);
return (int) iTimeStamp;
}
static void addListData (int TimeStamp, final String lat, final String lng, final String speed,
final String direction, final Context context){
int todaystamp = startOf("today");
int yesterdaystamp = startOf("yesterday");
String Datetime = DateFormat.format("dd-MM-yyyy kk:mm:ss", new Date(TimeStamp * 1000L)).toString();
SharedPreferences pref = context.getSharedPreferences("myPrefs", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
if (TimeStamp >= todaystamp) {
editor.putString("Today", "*headline=" + lat + ", " + lng + ";speed=" + speed + ";direction=" + direction + ";date=" + Datetime + ";");
} else if (TimeStamp >= yesterdaystamp) {
editor.putString("Yesterday", "*headline=" + lat + ", " + lng + ";speed=" + speed + ";direction=" + direction + ";date=" + Datetime + ";");
} else if (TimeStamp < yesterdaystamp) {
editor.putString("Older", "*headline=" + lat + ", " + lng + ";speed=" + speed + ";direction=" + direction + ";date=" + Datetime + ";");
}
editor.commit();
}
But now I'm stuck with one problem, when I add a item to the SharedPreferences on the same key it will overwrite the previous data. How can I add data to the same key without overwriting the previous data? Is it maybe possible to first get the data and then join the item to the data after that add the data to the SharedPreferences?
Any help you guys can provide me would be greatly appreciated! :good:
Alwaysup said:
As you guys pointed out, I'm now using SharedPreferences. I'm using this code:
Code:
static void addListData (int TimeStamp, final String lat, final String lng, final String speed,
final String direction, final Context context){
int todaystamp = startOf("today");
int yesterdaystamp = startOf("yesterday");
String Datetime = DateFormat.format("dd-MM-yyyy kk:mm:ss", new Date(TimeStamp * 1000L)).toString();
SharedPreferences pref = context.getSharedPreferences("myPrefs", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
if (TimeStamp >= todaystamp) {
editor.putString("Today", "*headline=" + lat + ", " + lng + ";speed=" + speed + ";direction=" + direction + ";date=" + Datetime + ";");
} else if (TimeStamp >= yesterdaystamp) {
editor.putString("Yesterday", "*headline=" + lat + ", " + lng + ";speed=" + speed + ";direction=" + direction + ";date=" + Datetime + ";");
} else if (TimeStamp < yesterdaystamp) {
editor.putString("Older", "*headline=" + lat + ", " + lng + ";speed=" + speed + ";direction=" + direction + ";date=" + Datetime + ";");
}
editor.commit();
}
But now I'm stuck with one problem, when I add a item to the SharedPreferences on the same key it will overwrite the previous data. How can I add data to the same key without overwriting the previous data? Is it maybe possible to first get the data and then join the item to the data after that add the data to the SharedPreferences?
Any help you guys can provide me would be greatly appreciated! :good:
Click to expand...
Click to collapse
SharedPreferences does not save data in subcategories, so the tag you give it to save a variable is then connected to that variable and if you use it again, it will be overridden (as you found out).
If you want to stick to the SharedPreferences, you have to give each item a unique tag, so you would normally add a counter to save "Today_1", "Today_2", Today_3", ...
then you save that counter also so that you know how many items you saved.
If you want to do it nicely though, check out the SQLite database. It is a little mor work and requires some knowledge about databases, but I think it's worth it.
Try static handlers. worth simple logic helps u to update ur activity from any thread or activity.
Related
Hi there!
I have been trying to catch the Cancel click of a DatePickerDialog, because I want to do some additional stuff, when the user clicks on the Cancel Button.
I tried it like described in the second answer from esilver from this Question:
http://stackoverflow.com/questions/...erner-of-datepicker-dialog?tab=active#tab-top
But I can't get it to work like that. When do I have to call this onClick method?
Would be great if someone could help me with that!
Thanks!
cTrox said:
Hi there!
I have been trying to catch the Cancel click of a DatePickerDialog, because I want to do some additional stuff, when the user clicks on the Cancel Button.
I tried it like described in the second answer from esilver from this Question:
http://stackoverflow.com/questions/...erner-of-datepicker-dialog?tab=active#tab-top
But I can't get it to work like that. When do I have to call this onClick method?
Would be great if someone could help me with that!
Thanks!
Click to expand...
Click to collapse
the "checked" solution in that example seems wrong to me. but the second one people voted up seems correct.
You can also set the onDissmissListener which will catch if the user backs out with the back key ( recommended for user friendliness )
have a look here:
http://developer.android.com/refere...id.content.DialogInterface.OnDismissListener)
Also, since DatePickerDialog is a subclass of AlertDialog, you can set the buttons the same way:
http://developer.android.com/guide/topics/ui/dialogs.html#AlertDialog
That should get you started but feel free to post back if you get stuck again. And post the code you are using.
Also, one other thing, it might be useful to keep a private reference to your dialog in your activity class.
All those examples (in the API docs and tutorials) always show a new dialog created when "onCreateDialog(int ID)" is called by the OS on your activity and they never save any sort of reference to it. They give you just enough code to hang yourself
Anyways, while this is a perfectly normal way to do things, it doesnt give you a chance to follow what is actually happening with the dialog. It also makes it harder to reference your dialog from elsewhere in the activity.
Keeping a reference, and exploring the onPrepareDialog(int ID) method are good for learning what the OS is doing with your dialog. (IMHO)
hth
Thanks a lot for your answers. But I still can't figure out how to do it.
Here's my current Code:
Code:
private DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker datePicker, int year, int monthOfYear,
int dayOfMonth) {
mYear = year;
mMonth = monthOfYear;
mDay = dayOfMonth;
// do some more stuff...
}
};
Code:
protected Dialog onCreateDialog(int id) {
Calendar cDate = Calendar.getInstance();
int cyear = cDate.get(Calendar.YEAR);
int cmonth = cDate.get(Calendar.MONTH);
int cday = cDate.get(Calendar.DAY_OF_MONTH);
switch(id){
case DATE_DIALOG_ID:
return new DatePickerDialog(this, mDateSetListener, cyear, cmonth, cday);
}
return null;
}
With that I can just call showDialog(DATE_DIALOG_ID); and I get the dialog. Now, where do I have to implement this OnDismissListener and how?
Thanks!
there are lots of ways to do this but I broke it out into several parts so hopefully it seems more obvious what is happening.
Code:
//here's our field reference we could use later or reuse or whatever
private DatePickerDialog dateDialog = null;
protected Dialog onCreateDialog(int id)
{
//your calendar code here... just removed to save space
switch(id)
{
case DATE_DIALOG_ID:
dateDialog = new DatePickerDialog(this, mDateSetListener, cyear, cmonth, cday);
dateDialog.setButton ( DialogInterface.BUTTON_NEGATIVE, android.R.string.cancel, cancelBtnListener );
dateDialog.setOnDismissListener ( listener );
break;
}
return dateDialog;
}
//our dismiss listener
protected DialogInterface.OnDismissListener dismissListener = new OnDismissListener( )
{
@Override
public void onDismiss ( DialogInterface dialog )
{
// do your thang here
}
};
//our click listener
protected DialogInterface.OnClickListener cancelBtnListener = new OnClickListener( )
{
@Override
public void onClick ( DialogInterface dialog, int which )
{
dialog.dismiss ( );
// since we dismiss here, the next listener to get called
// is the dismiss listener. now we'll have consistent behavoir
}
};
Ah thank you very much! I was always confused, where to set the Button and the OnDismissListener.
It works perfectly like that!
In my Android app, I have a sound that I want to play when a certain selection has been made from a spinner, but I want it to play the when the user actually makes the proper selection (or just after). My problem is that although the sound does play when they make the correct selection, as long as that selection stays chosen, it also plays every time the app starts up, when it should ONLY play at the time it's chosen. I think I need to change my setOnItemSelectedListener to setOnItemClickListener, but I'm not sure how (still pretty new to java). Can any generous soul out there show me how to change this up (assuming that's how to best solve this problem)?
Here is the code I have now:
Code:
fitnessSpinner = (Spinner) findViewById(R.id.fitness_spinner);
ArrayAdapter adapter4 = ArrayAdapter.createFromResource(
this, R.array.fitness_array, android.R.layout.simple_spinner_item);
adapter4.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
fitnessSpinner.setAdapter(adapter4);
fitnessSpinner.setOnItemSelectedListener(new OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long i) {
Log.d("test", "p: " + position + " " + i);
if(position == 0) {
//First Entry
MediaPlayer mp = MediaPlayer.create(mContext, R.raw.bowchica);
mp.start();
} if(position == 4) {
MediaPlayer mp = MediaPlayer.create(mContext, R.raw.debbie2);
mp.start();
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
I haven't try the below code but you can try it on your own and tell us.
In onCreate() declare MediaPlayer mp;
In every if statement that you use for check insert this code:
Code:
if(mp!=null){mp.release();}
int resid = R.raw.yoursound;
mp = MediaPlayer.create(this, resid);
After that override the methods onPause() and onResume() and insert this:
if(mp!=null){mp.release();}
If it is still playing a sound when you start your app, then you should check your code again if you have set as default option any of your selection options.
I would LOVE to try this out...Unfortunately, I'm way too dumb at this point point ot figure out exactly where those code snippets would go inside of what I already have.
Does anyone have a couple of minutes to show me where it would go?
Below is a sample code. Since i don't know your code I give you a snippet that you should adjust it to your code.
Code:
public class SampleSound extends Activity{
private Spinner fitnessSpinner;
private MediaPlayer mp;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);//here goes your layout
setViews();//here you will set all your views(spinners buttons textviews etc..)
setAdapters();//set your adapters here
setListeners();//
}
private void setListeners() {
fitnessSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long i) {
Log.d("test", "p: " + position + " " + i);
if(position == 0) {
//First Entry
if(mp!=null){mp.release();}
int resid = R.raw.bowchica;
mp = MediaPlayer.create(this, resid);
mp.start();
} if(position == 4) {
if(mp!=null){mp.release();}
int resid = R.raw.debbie2;
mp = MediaPlayer.create(this, resid);
mp.start();
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
private void setAdapters() {
ArrayAdapter adapter4 = ArrayAdapter.createFromResource(this, R.array.fitness_array, android.R.layout.simple_spinner_item);
adapter4.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
fitnessSpinner.setAdapter(adapter4);
}
private void setViews() {
fitnessSpinner = (Spinner) findViewById(R.id.fitness_spinner);
}
public void onResume(){
super.onResume();
if(mp!=null){mp.release();}
}
public void onPause(){
super.onPause();
if(mp!=null){mp.release();}
}
}
I really appreciate the help. I put the code in my routine, but it still plays the sound every time the activity is loaded (as long as the selection in the spinner is correct). It should only play the sound when the correct selection is made.
Any other ideas?
I am sure that your Spinner is set to some value (since you have values to display). Because your Spinner points to a selection (doesn't matter if you have selected or it is selected by default) your sound plays (even when you start the app).
A way to stop the sound playing at start is to declare and an other Item like you did with the previous 4 and set it as default selection of your Spinner.
To sum up:
1.You have to append in R.array.fitness_array an Item (like you did with the previous Items) and give it a name.
2.At the end of method setAdapters() insert this:
Code:
fitnessSpiner.setSelection(5);// or whatever is your selection number
Now it should work but you should know that this is not a good practice and you should try make a ListView or something else.
I'd be happy to change this out to a listview, or whatever would work. I just have to give my user a choice of 4 or 5 items, from which they can choose only one. Something like a drop down box, but in Android, I thought my only option was a spinner. But whatever I use, I have to be able to play a sound when certain items are chosen, but ONLY when those items are chosen, NOT whenever the activity is called up.
Any specific ideas of what I might change to?
What if I had another control like a textview or an edittext (with it's visibility property set to false) that I programatically populated with the users selection (when it's the selection that I want) and then have an OnItemClcickListener set to play the sound?
Could that work?
I will answer from the last to the top of your questions.
1.You can do whatever you want with android. You want TextViews and EditTexts with complex and nested Layouts you can do it. Write services that will communicate with your contacts through a content provider? You can do it.
Write, read and test code. Only this way you will actually learn.
2.Read developer.android.com. Read the android tutorials from there and specifically the Notepad example. You will learn a lot.
A good resource with small examples for ListViews is this.
3.Have you tried the changes I told you from the last post? Did it worked?
Since you just started with android and programming you must first be happy if you have the expected result and then read more to make your code better
Your suggested changes (fitnessSpiner.setSelection(5);// or whatever is your selection number) would stop the sound from playing, but defeat the apps purpose. Every time this activity is loaded, the spinners hit preferences to load the previously stored data. So if I force the spinner to a different selection to NOT play sound when the activity loads, then I would be displaying the wrong data for the user.
Yes you are right. So it is better to make a ListActivity. Read developer.android.com and the link i gave you before. You will be ok with this!
You're using "setOnItemSelectedListener", which sounds like when the app starts, its getting "selected" again.
Have you tried using "setOnItemClickListener" instead?
fitnessSpinner.setOnItemClickListener(new AdapterView.OnItemClickListener () {
public void onItemClicked() {}
};
Lakers16 said:
You're using "setOnItemSelectedListener", which sounds like when the app starts, its getting "selected" again.
Have you tried using "setOnItemClickListener" instead?
fitnessSpinner.setOnItemClickListener(new AdapterView.OnItemClickListener () {
public void onItemClicked() {}
};
Click to expand...
Click to collapse
onClickListener doesn't work for the spinner...I wish it did.
I REALLY need the drop down functionality of teh spinner, so I guess I'm going to try and figure out a way to have an invisible edittext that I set to the spinner selection and then use onClickListener or onChange...
Hey guys,
Is there any way to get the Android browser to handle key presses the same way a normal browser would? I'm mostly thinking about the arrow keys here. Usually, it just moves to the next link on the page. For example, try loading slides.html5rocks.com on an android device. Pushing the arrow keys should move to the next slide but instead it just highlights the links on the first slide. I'm trying this with a bluetooth keyboard but I assume it's the same on devices with physical keyboards.
On a side note, that website allows for swiping between slides. However, it does not do this when loaded in a desktop browser. Does anyone know how they did this?
Thanks
Edit: I just noticed that I posted this in the development section. I probably should have been in general. Sorry!
What exactly you want to get? Referenced site (html5rocks) work well (switching slides and so on) in HTML5 compliant browsers. For example in Google Chrome or in Firefox. Actually in Firefox 3.6.17 (version that I've tested) it works not exactly as expected but the mostly. And in my Android builtin browser it works probably as proposed. Left/right dragging gesture (on touch screen) has the same effect as pressing right/left button in desktop browser - swapping to the next/previous slide.
Anyways, if you'd like to deal with browser events, you probably should look at WebView class.
Yes, perhaps this was a bad example. What I'm wondering is if it is possible for android to interpret the arrow keys on a physical keyboard the same was as a desktop. This this particular example, you can just swipe, but I would like to be able to use the arrow keys on my keyboard to do this, just like I would on a desktop.
Maybe a better example would be http://htmlfive.appspot.com/static/gifter.html
this is impossible to use in android
the arrow keys should move your character, but they just scroll the page
I see... Well, the hack below should do what you want, but for some reason it doesn't.
Code:
public class WebActivity extends Activity {
private static final String TAG = "WebActivity";
WebView webView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new HelloWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.setOnKeyListener(onKeyListener);
webView.addJavascriptInterface(new JavaScriptInterface(), "Android"); // this is for debug only
webView.loadUrl("http://htmlfive.appspot.com/static/gifter.html");
// webView.loadUrl("file:///android_asset/gifter.html");
}
// This is for debug - redirect Android.log() javascript calls to Log.d().
// 'Android' here - is an 'interfaceName argument' of addJavascriptInterface() call above
public class JavaScriptInterface {
public void log(String message) {
Log.d(TAG, message);
}
}
private void simulateKeyEvent(String key, int code, boolean keyDown) {
Log.d(TAG, "simulateKeyEvent('" + key + "', " + code + ", " + keyDown + ")");
webView.loadUrl("javascript:(function(){var e=document.createEvent('KeyboardEvent');e.initKeyboardEvent('" + (keyDown ? "keydown" : "keyup" ) + "',true,true,null,'" + key + "',0,0,0," + code + ",0);document.body.dispatchEvent(e);})()");
}
OnKeyListener onKeyListener = new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d(TAG, ".onKey(): keyCode = " + keyCode + ", action = " + event.getAction());
int code;
String key;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_LEFT:
code = 37; // JavaScript KeyboardEvent.keyCode value for left arrow
key = "Left";
break;
case KeyEvent.KEYCODE_DPAD_UP:
code = 38; // ...
key = "Up";
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
code = 39;
key = "Right";
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
code = 40;
key = "Down";
break;
default:
Log.d(TAG, "Unknown key");
return false;
}
boolean keyDown;
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
keyDown = true;
break;
case KeyEvent.ACTION_UP:
keyDown = false;
break;
default:
Log.d(TAG, "Unknown action");
return false;
}
simulateKeyEvent(key, code, keyDown);
return true;
}
};
private class HelloWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
}
Looks like the problem is in the implementation of initKeyboardEvent() in WebKit (or V8?). It always produces KeyboardEvent object with 0 values of keyCode and keyChar. So this code doesn't working in my Chrome too: event is dispatched, appropriate handler is called, but keyCode is 0.
Probably there is some other way to simulate keyboard event for JavaScript running within WebView. Or maybe there is some way to redefine KeyEvent processing by WebView. I think you should look for something like this.
This is interesting subject. If you'll find a solution, please write here about it.
References:
http://developer.android.com/resources/tutorials/views/hello-webview.html - basics of WebView usage
http://developer.android.com/reference/android/webkit/WebView.html - WebView in more details
http://lexandera.com/2009/01/injecting-javascript-into-a-webview/ - about interacting with JavaScript from WebView
http://stackoverflow.com/questions/1897333/firing-a-keyboard-event-on-chrome (and many other topics) - about problems with simulating keyboard events on WebKit
this is really frustrating. No matter what I do, I just end up with keycode 0. google really needs to fix the problem with initKeyboardEvent. Oh well..
Thanks for you help
Hi!
My self Raj, i have a problem when using the split action in my application.
i am doing an E-Menu for an restaurant. i list out all available category in major listview if the user click on the item of major list it should display all available minor items of its in behind of the Major listview.
I found one solution in Google it is possible by using split action.
Can anyone guide me / give some sample i may know about it..,
I am waiting for your guide.,
Have A Happy Day..,
Thanks to all..,
Simply add the following line to your <activity> or <application> tag in your AndroidManifest :
Code:
uiOptions="splitActionBarWhenNarrow"
EDIT : As a side note, it seems you want the split actionbar to be displayed only after the user clicked something, in that use case, the Contextual ActionBar seems more suited.
To use it, simply define your actionbar items in a menu.xml just like the normal actionbar, then in your java code use something like :
Code:
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item1:
//do something
mode.finish();
return true;
case R.id.menu_item2:
// do something else
mode.finish();
return true;
case R.id.menu_item3:
// etc....
mode.finish();
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
And in the onClickListener() of the component that triggers the contextual ActionBar, call it like that :
Code:
if (mActionMode != null)
// Do nothing
else
mActionMode = startActionMode(mActionModeCallback);
You might want to use the ActionBarSherlock Library in order to keep compatibility with gingerbread/froyo
Hello,
I create that thread to present you a tutorial learning you to save data with SQLite on Android. This tutorial is also available in video on Youtube :
Learn to save data with SQLite on Android
On Android, there are several solutions to persist data between users’ sessions. One solution is to use a relational database to persist data and then to be able to query easily these data. In standard, Android SDK comes with a SQLite implementation. Biggest advantage of SQLite integration to Android OS is the fact that there is no need to to setup the database. So, no administration of this database. SQLite is embedded in standard and each application can have its SQLite database.
The only job that developers must make is to define SQL tables and statements for creating and updating data. Access to an SQLite database involves accessing the file system. So, it can be a slow operation. To avoid ANR (Application Not Responding) errors, it’s recommended to perform database operations asynchronously.
When an application creates and uses a SQLite database, it will be saved by default in the directory : DATA/data/APP_PACKAGE/databases/FILENAME .
1. Architecture
All classes needed to manage databases in Android SDK are contained in the package android.database . The package android.database.sqlite contains the SQLite specific classes.
SQLite API is centered around 2 main classes :
SQLiteOpenHelper that is an helper class to extend to manage database operations.
SQLiteDatabase that is the base class for working with a SQLite database in Android.
2. SQLiteOpenHelper
When you want to work with a SQLite database in Android, you must extend SQLiteOpenHelper class. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
You need also to override the following methods :
onCreate() that is called when database is accessed but not yet created.
onUpgrade() called when you choose to increment the version number of the database. In this method you can manage the migration process between two databases versions.
Both methods get and SQLiteDatabase instance in parameter which is the way to communicate with the database.
Furthermore, SQLiteOpenHelper provides 2 methods to get access to an SQLiteDatabase instance object respectively in read and in write modes :
getReadableDatabase() for read mode.
getWriteableDatabase() for write mode.
3. SQLiteDatabase
SQLiteDatabase is the class used to communicate with a SQLite database. It exposes several methods to interact with database like insert(), update() or delete().
In addition, it lets you to make queries via rawQuery() to queries made directly in SQL or via query() method. This last method provides a structured interface for specifying a SQL query.
4. Practice
Now, you know theory about SQLite in Android context. We can put in practice all the concepts. To achieve that, we’re going to make a database with a players table letting us to store NBA players.
To start, we create a simple Player Java POJO :
Code:
public class Player {
private int id;
private String name;
private String position;
private int height;
public Player() {
}
public Player(int id, String name, String position, int height) {
this.id = id;
this.name = name;
this.position = position;
this.height = height;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
return name + " - " + position + " - " + height + " cm";
}
}
Then, we must create the SQLiteOpenHelper extended class to manage our application database. Code is here :
Code:
package com.ssaurel.samples.sqlite;
import java.util.LinkedList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class SQLiteDatabaseHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "PlayersDB";
private static final String TABLE_NAME = "Players";
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_POSITION = "position";
private static final String KEY_HEIGHT = "height";
private static final String[] COLUMNS = { KEY_ID, KEY_NAME, KEY_POSITION,
KEY_HEIGHT };
public SQLiteDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATION_TABLE = "CREATE TABLE Players ( "
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT, "
+ "position TEXT, " + "height INTEGER )";
db.execSQL(CREATION_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// you can implement here migration process
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
this.onCreate(db);
}
public void deleteOne(Player player) {
// Get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, "id = ?", new String[] { String.valueOf(player.getId()) });
db.close();
}
public Player getPlayer(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
if (cursor != null)
cursor.moveToFirst();
Player player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
return player;
}
public List<Player> allPlayers() {
List<Player> players = new LinkedList<Player>();
String query = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Player player = null;
if (cursor.moveToFirst()) {
do {
player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
players.add(player);
} while (cursor.moveToNext());
}
return players;
}
public void addPlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
// insert
db.insert(TABLE_NAME,null, values);
db.close();
}
public int updatePlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
int i = db.update(TABLE_NAME, // table
values, // column/value
"id = ?", // selections
new String[] { String.valueOf(player.getId()) });
db.close();
return i;
}
}
Database is created in the constructor of the extended class. Players table is created in the onCreate() method thanks to a SQL statement.
In our class, we add methods to add a new player, to delete an existing one, to update and then a method to get all the players in the table. In this last method, we use a Cursor object to iterate on rows and then build equivalent Player instances.
To use our class to create some players then display on a simple ListView, we can use the following code :
Code:
public class MainActivity extends Activity {
private SQLiteDatabaseHandler db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create our sqlite helper class
db = new SQLiteDatabaseHandler(this);
// create some players
Player player1 = new Player(1, "Lebron James", "F", 203);
Player player2 = new Player(2, "Kevin Durant", "F", 208);
Player player3 = new Player(3, "Rudy Gobert", "C", 214);
// add them
db.addPlayer(player1);
db.addPlayer(player2);
db.addPlayer(player3);
// list all players
List<Player> players = db.allPlayers();
if (players != null) {
String[] itemsNames = new String[players.size()];
for (int i = 0; i < players.size(); i++) {
itemsNames[i] = players.get(i).toString();
}
// display like string instances
ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, itemsNames));
}
}
}
Execution result can be seen here :
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
SQLite implementation in Android is simple and really powerful. You can now use it in your Android application to persist data.
Don't hesitate to give it a try and give me your feedbacks about this tutorial.
Thanks.
Sylvain
Hey, I have made a preview for SQLite database earlier this month for my friend.
If anyone's interested then it's there at https://www.GitHub.com/Fifa2151/SQLiteTest
Thanks,
Raj.
Sent from my Pixel using Tapatalk
sylsau said:
Hello,
I create that thread to present you a tutorial learning you to save data with SQLite on Android. This tutorial is also available in video on Youtube :
Learn to save data with SQLite on Android
On Android, there are several solutions to persist data between users’ sessions. One solution is to use a relational database to persist data and then to be able to query easily these data. In standard, Android SDK comes with a SQLite implementation. Biggest advantage of SQLite integration to Android OS is the fact that there is no need to to setup the database. So, no administration of this database. SQLite is embedded in standard and each application can have its SQLite database.
The only job that developers must make is to define SQL tables and statements for creating and updating data. Access to an SQLite database involves accessing the file system. So, it can be a slow operation. To avoid ANR (Application Not Responding) errors, it’s recommended to perform database operations asynchronously.
When an application creates and uses a SQLite database, it will be saved by default in the directory : DATA/data/APP_PACKAGE/databases/FILENAME .
1. Architecture
All classes needed to manage databases in Android SDK are contained in the package android.database . The package android.database.sqlite contains the SQLite specific classes.
SQLite API is centered around 2 main classes :
SQLiteOpenHelper that is an helper class to extend to manage database operations.
SQLiteDatabase that is the base class for working with a SQLite database in Android.
2. SQLiteOpenHelper
When you want to work with a SQLite database in Android, you must extend SQLiteOpenHelper class. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
You need also to override the following methods :
onCreate() that is called when database is accessed but not yet created.
onUpgrade() called when you choose to increment the version number of the database. In this method you can manage the migration process between two databases versions.
Both methods get and SQLiteDatabase instance in parameter which is the way to communicate with the database.
Furthermore, SQLiteOpenHelper provides 2 methods to get access to an SQLiteDatabase instance object respectively in read and in write modes :
getReadableDatabase() for read mode.
getWriteableDatabase() for write mode.
3. SQLiteDatabase
SQLiteDatabase is the class used to communicate with a SQLite database. It exposes several methods to interact with database like insert(), update() or delete().
In addition, it lets you to make queries via rawQuery() to queries made directly in SQL or via query() method. This last method provides a structured interface for specifying a SQL query.
4. Practice
Now, you know theory about SQLite in Android context. We can put in practice all the concepts. To achieve that, we’re going to make a database with a players table letting us to store NBA players.
To start, we create a simple Player Java POJO :
Code:
public class Player {
private int id;
private String name;
private String position;
private int height;
public Player() {
}
public Player(int id, String name, String position, int height) {
this.id = id;
this.name = name;
this.position = position;
this.height = height;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
return name + " - " + position + " - " + height + " cm";
}
}
Then, we must create the SQLiteOpenHelper extended class to manage our application database. Code is here :
Code:
package com.ssaurel.samples.sqlite;
import java.util.LinkedList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class SQLiteDatabaseHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "PlayersDB";
private static final String TABLE_NAME = "Players";
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_POSITION = "position";
private static final String KEY_HEIGHT = "height";
private static final String[] COLUMNS = { KEY_ID, KEY_NAME, KEY_POSITION,
KEY_HEIGHT };
public SQLiteDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATION_TABLE = "CREATE TABLE Players ( "
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT, "
+ "position TEXT, " + "height INTEGER )";
db.execSQL(CREATION_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// you can implement here migration process
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
this.onCreate(db);
}
public void deleteOne(Player player) {
// Get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, "id = ?", new String[] { String.valueOf(player.getId()) });
db.close();
}
public Player getPlayer(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
if (cursor != null)
cursor.moveToFirst();
Player player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
return player;
}
public List<Player> allPlayers() {
List<Player> players = new LinkedList<Player>();
String query = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Player player = null;
if (cursor.moveToFirst()) {
do {
player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
players.add(player);
} while (cursor.moveToNext());
}
return players;
}
public void addPlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
// insert
db.insert(TABLE_NAME,null, values);
db.close();
}
public int updatePlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
int i = db.update(TABLE_NAME, // table
values, // column/value
"id = ?", // selections
new String[] { String.valueOf(player.getId()) });
db.close();
return i;
}
}
Database is created in the constructor of the extended class. Players table is created in the onCreate() method thanks to a SQL statement.
In our class, we add methods to add a new player, to delete an existing one, to update and then a method to get all the players in the table. In this last method, we use a Cursor object to iterate on rows and then build equivalent Player instances.
To use our class to create some players then display on a simple ListView, we can use the following code :
Code:
public class MainActivity extends Activity {
private SQLiteDatabaseHandler db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create our sqlite helper class
db = new SQLiteDatabaseHandler(this);
// create some players
Player player1 = new Player(1, "Lebron James", "F", 203);
Player player2 = new Player(2, "Kevin Durant", "F", 208);
Player player3 = new Player(3, "Rudy Gobert", "C", 214);
// add them
db.addPlayer(player1);
db.addPlayer(player2);
db.addPlayer(player3);
// list all players
List<Player> players = db.allPlayers();
if (players != null) {
String[] itemsNames = new String[players.size()];
for (int i = 0; i < players.size(); i++) {
itemsNames[i] = players.get(i).toString();
}
// display like string instances
ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, itemsNames));
}
}
}
Execution result can be seen here :
SQLite implementation in Android is simple and really powerful. You can now use it in your Android application to persist data.
Don't hesitate to give it a try and give me your feedbacks about this tutorial.
Thanks.
Sylvain
Click to expand...
Click to collapse
Awesome guide @sylsau...
Also, do you know how to make a flashify type app but only for a specific zip?
When you want to work with a SQLite database in Android, you must extend SQLiteOpenHelper class. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
Click to expand...
Click to collapse
You don't actually need to use a subclass of SQLiteOpenHelper you can use the SQliteDatabase's open????? methods.
Furthermore, SQLiteOpenHelper provides 2 methods to get access to an SQLiteDatabase instance object respectively in read and in write modes :
Click to expand...
Click to collapse
Actually, in either case, except if the database cannot be opened, for write, both getReadableDatabase and getWritableDatabase will open a database that can be written to. As per :-
Create and/or open a database. This will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned. If the problem is fixed, a future call to getWritableDatabase() may succeed, in which case the read-only database object will be closed and the read/write object will be returned in the future.
Click to expand...
Click to collapse
as per developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper#getReadableDatabase()
On occasions people new to SQLite sometimes wonder why no database exists after they have instantiated the subclass of SQLiteOpenHelper (aka the DatabaseHelper). This is because the database is only created when either getWritableDatabase or getReadableDatabase is called. With a single line added to the constructor, the constructor will create the database (and thus invoke the onCreate method) e.g.
Code:
public SQLiteDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.getWritableDatabse();
}
AUTOINCREMENT is perhaps the most commonly misused keyword (perhaps wrongly named). It does not make the column automatically generate a unique ID. It is INTEGER PRIMARY KEY that does this, as it make the column an alias of the **rowid**.
Rather AUTOINCREMENT compliments INTEGER PRIMARY KEY adding a constraint that the generated ID must be larger that any ID that exists or have existed. However, this is a moot point as it's only when the largest possible ID has been assigned (9223372036854775807) that it comes into play (other than without AUTOINCREMENT a deleted highest ID will be resused). At this point a table with AUTOINCREMENT will then fail with an SQLITE_FULL exception (without AUTOINCREMENT will attempt to assign a free lower ID rather than fail). However, AUTOINCREMENT has overheads (using a limited test I came up with an 8-12% degradation in performance when inserting). This is due to a changed algorithm being used that utilises another table sqlite_sequence that stores the highest allocated ID.
The SQLite documentation states :-
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed. It is usually not needed.
Click to expand...
Click to collapse
sqlite.org/autoinc.html
There are a few issues with the code, such as :-
You should always close Cursors when finished with them (not doing so may result in too many databases /database objects open exception ).
Checking a Cursor for null after a Cursor is returned from a call to an SQLiteDatabase method that returns a Cursor serves no purpose. A valid Cursor will always be returned. If there is no data then using a Cursor moveTo????? method will return false is the move cannot be made, alternately the getCount() method will return the number of rows in the Cursor.
If there were now rows in the Players table, the the code would fail with an error when an attempt is made to retrieve data at
Code:
player.setId(Integer.parseInt(cursor.getString(0)));
Issues regarding mis-calculated column offsets can be reduced by taking advantage of the Cursor's **getColumnIndex** method.
As such, as an example, the getPlayer method would be improved if changed to :-
Code:
public Player getPlayer(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
Player player = new Player(); //<<<<<<<<<< Always have a Player to return (should check for default player to indicated )
if (cursor.moveToFirst()) {
player.setId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_ID))));
player.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
player.setPosition(cursor.getString(cursor.getColumnIndex(KEY_POSITION)));
player.setHeight(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_HEIGHT))));
}
cursor.close(); //<<<<<<<<<< Important to close a Cursor
return player;
}