java.lang.ArrayIndexOutOfBoundsException on android input form - java

I have an input form that has 38 fields
I know it's too much but my boss want it to be like that
There are 4 edit texts and spinners as the rest and 1 imageView that'll be uploaded to server using http client
I use AsyncTask to send the data like this :
new asyncTask().execute(array, array, array);
Because there's too many of items, I think I missed one of them
I've checked many times but I still get the indexOutOfBounds exception
Can you help me find them or give me solution / advice to make simpler code
Here's the code (your eyes might hurt coz it's the whole code) :
http://pastebin.com/0dUss9ak
(it's too much to write here)
Why i'm using alphabets for the variable's name?
If I use name for each of them i'll be dead.
Thanks before

On this line
new KirimData().execute(id_user, nama, lokasi, keterangan, a, b, c, d, e, f, g, h, i, k, l, m, n, o, p, q, ad, bd, cd, dd, ed, fd, gd, hd, id, jd, kd, ld, md, nd, od, pd, qd, savedImagePath);
You seem to be missing parameter j, which will (very probably) cause an exception in
KirimData#doInBackground

To make your code and variables easier to manage, I would highly recommend using HashMaps that use the field names (i.e. a, b, c, etc. in your code) as keys:
HashMap<String, String> fieldValues = new HashMap<String, String>();
HashMap<String, Spinner> fieldSpinners = new HashMap<String, Spinner>();
You could drastically reduce your code replication (and the mistakes like this that code replication brings about) by iterating over the keys in your HashMap and executing the same same logic during each iteration (as opposed to copying/pasting the same lines of code for each field).
Also, I would recommend using more meaningful field names. It might not yield as compact code as you have now, but it will be easier to read and maintain in the long run.

Actually I found a malicious code in onCreate:
File nfile = new File(Environment.getExternalStorageDirectory()+"/Android/data/com.nigmagrid.jm.demo/");
nfile.mkdir();
why you always create directory every time the application start ?
If you want really bad to put that many spinner,
I suggest you should add your spinner on the way which add it programmatically.
- First you may inflating your main layout
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
ViewGroup inflatedLayout = (ViewGroup) inflater.inflate(<your layout xml>, null);
Then put the Spinner content on ArrayAdapter
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapter.add("Jembatan 1");
adapter.add("Jembatan 2");
adapter.add("Jembatan 3");
I don't know if every Spinner have a different content.
if they did, you may declare different adapter or create it from a resource.
Then add all spinner that you want:
for(int i=0;i<35;i++){
Spinner s = new Spinner(this);
s.setAdapter(adapter);
s.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Spinner s = (Spinner) parent;
String selectedItem = (String) s.getSelectedItem();
Toast.makeText(InflateCoba.this, selectedItem, Toast.LENGTH_SHORT).show();
// or you can assign it to a variable
// selectedStr[i] = selectedItem;
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
inflatedLayout.addView(s);
}
set as main View
setContentView(inflatedLayout);
on btn_proses click listener, I suggest you should not create new Object of asyncTask,
declare it in initialization and use the instance that you declare.
HashMap<String, Object> kirimPaket = new HashMap<String, Object>();
kirimPaket.put("nama", nama);
kirimPaket.put("keterangan", keterangan); // and do the rest ..
kirimPaket.put("spinnerItem", selectedStr);
kirim.execute(kirimPaket);
which kirim is an instance of KirimData.
Use HashMap and put your packet on there, it will make it simple.
protected class KirimData extends AsyncTask<HashMap<String, Object>, Void, String>
Actually I don't like the way asyncTask send parameters, Google should do it simple.
then the finalize it
#Override
protected String doInBackground(HashMap<String, Object>... params) {
try{
HttpClient httpClient = CustomHttpClient.getHttpClient();
HttpPost postRequest = new HttpPost(VarsUrl.getServerAddress()+"simpan-inspeksi-jembatan.php");
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
String nama = params[0].get("nama");
String keterangan = params[0].get("keterangan"); // and do the rest ..
String[] selectedStr = params[0].get("spinnerItem");
reqEntity.addPart("nama", new StringBody(nama));
reqEntity.addPart("keterangan", new StringBody(keterangan)); // and do the rest ..
for(int i=0;i<selectedStr.length;i++){
reqEntity.addPart("item_"+i, new StringBody(selectedStr[i]));
}
....

Related

Remove the first element of the String array in Java : Android

Let say I have this String array "{Unclaimed", "Lost/Stolen", "Damaged/Defective", "Pawned", "Not Turned Over", "Others"} and I want to remove the first one which is Unclaimed , It will remove if aat_distribution_status is being clicked is there anyway to remove it? I tried Reasons = Reasons.Skip(1).ToArray() but it doesn't work
My sample code
AutoCompleteTextView aat_reason_not_presented;
aat_reason_not_presented = findViewById(R.id.aat_reason_not_presented);
String[] Reasons = new String[]{"Unclaimed", "Lost/Stolen", "Damaged/Defective", "Pawned", "Not Turned Over", "Others"};
ArrayAdapter<String> adapterYesNo = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, Reasons);
adapterYesNo.setDropDownViewResource(simple_spinner_dropdown_item);
aat_reason_not_presented.setAdapter(adapterYesNo);
aat_distribution_status.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View arg1, int pos, long id) {
Reasons = Reasons.Skip(1).ToArray() //Trying to remove first element of reasons but it didn't work
}
});
You can use Arrays.copyOfRange(T[], int, int) like
Reasons = Arrays.copyOfRange(Reasons, 1, Reasons.length);
Also, Java variable names start with a lowercase letter by convention. Finally, I suspect that Reasons must be effectively final to use it in the inner class like that. So I doubt that will work as is.

index list view with database cardview

I know there are alot of duplicates with issues like these but pleas do read mine and help me out.
I am very new to Android development as such I coded these with my own instincts and limited guides available.
I'd like to implement an indexable (A-Z) side panel just like in contacts. All the posts available are array strings with hard-coded entries but mine aren't, I am using DB Browser for SQLite and then populate each data in a cardview.
I have referred to (https://github.com/woozzu/IndexableListView/blob/master/src/com/woozzu/android/widget/IndexableListView.java) and tried all the solutions mentioned related to this post but to no avail. I believe I simply coded it the wrong way as the entries are hard-coded but mine aren't.
I am currently following this guide, (http://androidopentutorials.com/android-listview-with-alphabetical-side-index/) and have amended some codes here and there which I thought is necessary for my situation, such as adding my database into an array. However, there are multiple errors and I don't know what to do.
As such, I have no idea how to solve these errors proceed on. Please do help me out and provide me with, perhaps a step-by-step tutorial or even better video guides so that I could follow through.
Below are what I have tried:
Declaration
//indexable list view
Map<String, Integer> mapIndex;
List<String> dbList = new ArrayList<>();
OnCreate
//indexable list view
String[] dbList= database.getKeyword();
Arrays.asList(dbList);
dbList.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_expandable_list_item_1, dbList));
etIndexList(dbList);
displayIndex();
//indexable list view
private void getIndexList(String[] dbList){
mapIndex = new LinkedHashMap<String, Integer>();
for(int i = 0; i < dbList.length; i++){
String db = dbList[i];
String index = db.substring(0,1);
if(mapIndex.get(index) == null)
mapIndex.put(index, i);
}
}
private void displayIndex(){
LinearLayout indexLayout = (LinearLayout) findViewById(R.id.side_index);
TextView textView;
List<String> dbList = new ArrayList<String>(mapIndex.keySet());
for (String index : dbList){
textView = (TextView) getLayoutInflater().inflate(R.layout.side_index_item, null);
textView.setText(index);
textView.setOnClickListener(this);
indexLayout.addView(textView);
}
}
public void onClick(View view){
TextView selectedIndex = (TextView) view;
dbList.setSelection(mapIndex.get(selectedIndex.getText()));
}
The errors are:
If you require any more codes do let me know and I will update this post. Thank you in advance.
follow this lib for indexing list no need to write extra function this lib manage all the case
Answer to the errors that you are getting:
You are calling dbList.setAdapter(): dbList is not a ListView or RecyclerView
Call setAdapter() method on appropriate ListView or RecyclerView variable.
You are passing this to setOnClickListener() method: this is pointing to your KnowledgeActivity and not a View.OnClickListener.
Solution: Either implement View.OnClickListener in your activity or call new OnClickListener like this,
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}});
database.keyword() returns List and you are trying to cast it to String[]

Deleting items from a listview troubles

So i'm learning android development and i started my first project a few weeks ago. Since then i've hit a few roadblocks but i've gotten past them. This one is different.
I'm trying to make it so when the user touches and holds on an item in a listview a dialogue boc pops up asking if they are sure and on Yes click it will delete the item. Simple enough right?
well here's my code:
//passwordList is a Set<String> and so is passList
final Set<String> passwordList = mPrefs.getStringSet("pass", new HashSet<String>());
if (passwordList != null) {
passList = passwordList;
listFinal = passList.toArray(new String[passList.size()]);
list2 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listFinal);
passwordListView.setAdapter(list2);
//onClickListener for the main list
passwordListView.setLongClickable(true);
passwordListView.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View strings, final int i, long l) {
AlertDialog.Builder deleteConf = new AlertDialog.Builder(main.this);
final int positionToRemove = i;
deleteConf.setTitle("Delete Password?");
deleteConf.setMessage("Are you sure you want to delete the password '" +listFinal[i] +"'?");
deleteConf.setNegativeButton("No", null);
deleteConf.setPositiveButton("Yes", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int w) {
Log.d("dialog", "Pressed YES");
passwordList.remove(positionToRemove);
ArrayList<String> list = new ArrayList<String>(Arrays.asList(listFinal));
//Is this right?
passList.remove(positionToRemove);
//Or this one?
list.remove(positionToRemove);
list2.notifyDataSetChanged();
list2.notifyDataSetInvalidated();
}
});
deleteConf.show();
return false;
}
});
}
I feel like i'm not removing the item from the correct array. Since the Adapter source is set to listFinal I should remove the item from there right? but it won't let me call listFinal.remove(positionToRemove);
Can anyone help me figure out what's wrong here? the dialogue box shows but when I click yes nothing happens. It knows that i pressed yes (hence the log.d pressed YES) but the item is never removed.
First thing that i noticed is you have 2 objects: list and list2 and u call
list.remove();
list2.notifyDataSetChanged();
I dont see the rest of the code but this might be the case.
listFinal should have been an ArrayList and not just an array

How to get a string from strings.xml by adding int to the name

private int info = 1;
public void nextStep(View view)
{
TextView textInfo = (TextView) findViewById(R.id.textInfo);
textInfo.setText(R.string.info1);
info++;
}
When one button is clicked, method nextStep is called. And every time a button clicked, I want to show different info, first time it's info1 string, next time it's info2 string and etc. from strings.xml. I would like to do something like that:
private int info = 1;
public void nextStep(View view)
{
TextView textInfo = (TextView) findViewById(R.id.textInfo);
textInfo.setText(R.string.info + info);
info++;
}
Of course, it's not possible. What should I do? I really don't want to write a big if/else or switch statement. Thanks.
Of course, it's not possible.
Actually, it is. You can use getIdentifier to do this:
private int info = 1;
public void nextStep(View view)
{
TextView textInfo = (TextView) findViewById(R.id.textInfo);
int myStrId = textInfo.getContext().getResources().getIdentifier("info"+info, "string", textInfo.getContext().getPackageName());
textInfo.setText(myStrId);
info++;
}
getIdentifer() is a way to fetch resource IDs that are stored in R if you don't know the exact name. While it isn't the most efficient method in the world, it suffices in situations where referencing R (such as your situation) is not possible.
The method returns the same ID that R would; that is, getIdentifier("info1", "id", ...); is the same as R.id.info1, since R is just a compiled version of it. This method also works in the event that you are unsure if an ID exists (such as from an external library) but need to reference it anyway.
Use an array of String or better a List<String> such as an ArrayList<String> and fill it with the Strings from the XML. Then you can use the get(int index) method to get the ith String in the list.
If you are using JAXB to unmarshall your XML, you can have it set up to create your List for you without much fuss.

Populating single ListView with different row layouts

I am attempting to populate a ListView with a column from a database. I can achieve this successfully, but the problem is i would like to use a different layout resource depending on if the id matches a PendingIntent.
This is to check if an alarm exists with the rowid, and i plan to have visual feedback in the listview to show the user which alarms exist. I can successfully check the rowid against PendingIntents and get a return boolean.
The issue I run into is populating the ListView with different layout resources for different rows (is this even possible?) and i have no idea where to go from here.
I currently have the following code:
for(int x = 0; x < numNotes; x++) {
if(existAlarm(intarray[x])){
String[] from = new String[] { TodoDbAdapter.KEY_SUMMARY };
int[] to = new int[] { R.id.label1};
cursor = dbHelper.fetchTodo(intarray[x]);
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.todo_row_green, cursor, from, to);
setListAdapter(notes);
} else if (!existAlarm(intarray[x])){
String[] from = new String[] { TodoDbAdapter.KEY_SUMMARY };
int[] to = new int[] { R.id.label};
cursor = dbHelper.fetchTodo(intarray[x]);
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.todo_row, cursor, from, to);
setListAdapter(notes);
}
}
But the ListView just shows the final database entry from the loop.
I would be very grateful for any guidance, Thanks.
Of course, only the last item will be shown. This is because you keep changing the list adapter each time you enter the loop and execute. Get rid of the loop.
If I understand correctly, you want to display a either a green row or not depending on the ToDo. If so, write your own list adapter which is a subclass of the SimpleCursorAdapter. Then override the newView (Context context, Cursor cursor, ViewGroup parent) method to choose view to use to display the row. The cursor parameter is already moved to the correct position, so you can retrieve values from the DB for any necessary comparisons.
For example: I assume (because of the fetchTodo(intarray[x])) that you are comparing based on the id of the ToDo. In that case your code may look like:
public View newView (Context context, Cursor cursor, ViewGroup parent){
long id = cursor.getLong(TodoDbAdapter.ROW_ID_COLUMN);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (existAlarm(id)){
return inflater.inflate(R.layout.todo_row_green, null);
} else {
return inflater.inflate(R.layout.todo_row, null);
}
}
I don't know if I understood your code well, but you can adapt this to suit your needs.
Its quite possible to use a different view in each row: you however can't use a standard SimpleCursorAdapter for it: you have to overload the getView() function. An example is at Trying to override getView in a SimpleCursorAdapter gives NullPointerExceptio (there are a couple of errors which are answered in the post, but the basic technique is correct).
As far as showing only the last post, your code is creating a NEW SimpleCursorAdapter for every row, which is incorrect. You want to use the getView() override and then do the for loop and comparison in there.

Categories

Resources