so the app i am working on ran into an issue, the app crashes only on Android 7 and up. from the logcat the error seems to happen on my parcelable class.
here is the point where the crash happens(the class which has the parcelable):
public class LookupCriteriaBean implements Parcelable, Serializable {
private String lookupCode;
private String lookupField;
private String lookupDisplayName;
private String lookupSearchValue;
public LookupCriteriaBean(){
}
public LookupCriteriaBean(String s) {
if (s == null || "".equals(s.trim()))
throw new IllegalArgumentException("Invalid lookup criteria setting from server!");
int idx = 0;
String[] arrS = Tool.split(s, Global.DELIMETER_DATA);
lookupCode = arrS[idx++];
lookupField = arrS[idx++];
lookupDisplayName = arrS[idx++];
}
public LookupCriteriaBean(Parcel in) {
String[] arrS = new String[LookupCriteriaBean.class.getFields().length];
in.readStringArray(arrS);
int idx = 0;
lookupCode = arrS[idx++];
lookupField = arrS[idx++];
lookupDisplayName = arrS[idx++];
}
public String getLookupCode() {
return lookupCode;
}
public void setLookupCode(String lookupCode) {
this.lookupCode = lookupCode;
}
public String getLookupField() {
return lookupField;
}
public void setLookupField(String lookupField) {
this.lookupField = lookupField;
}
public String getLookupDisplayName() {
return lookupDisplayName;
}
public void setLookupDisplayName(String lookupDisplayName) {
this.lookupDisplayName = lookupDisplayName;
}
public String toString() {
return lookupDisplayName;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] { lookupCode, lookupField, lookupDisplayName });
}
public static final Parcelable.Creator<LookupCriteriaBean> CREATOR = new Parcelable.Creator<LookupCriteriaBean>() {
public LookupCriteriaBean createFromParcel(Parcel source) {
return new LookupCriteriaBean(source);
}
public LookupCriteriaBean[] newArray(int size) {
return new LookupCriteriaBean[size];
}
};
public String getLookupSearchValue() {
return lookupSearchValue;
}
public void setLookupSearchValue(String lookupSearchValue) {
this.lookupSearchValue = lookupSearchValue;
}
}
the line which triggers the crash is in.readStringArray(arrS);
the problem is the crash only happens on android 7 and above, it doesn't happen on any other devices i tested on, i have no idea what is causing this since the app runs fine on everything else except nougat devices.
here is the logcat output:
E/AndroidRuntime( 3868): FATAL EXCEPTION: main
E/AndroidRuntime( 3868): Process: com.adins.msmfif, PID: 3868
E/AndroidRuntime( 3868): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.adins.msmfif/com.adins.msm.LookupActivity}: java.lang.RuntimeException: bad array lengths
E/AndroidRuntime( 3868): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
E/AndroidRuntime( 3868): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
E/AndroidRuntime( 3868): at android.app.ActivityThread.-wrap12(ActivityThread.java)
E/AndroidRuntime( 3868): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
E/AndroidRuntime( 3868): at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 3868): at android.os.Looper.loop(Looper.java:154)
E/AndroidRuntime( 3868): at android.app.ActivityThread.main(ActivityThread.java:6077)
E/AndroidRuntime( 3868): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 3868): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
E/AndroidRuntime( 3868): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
E/AndroidRuntime( 3868): Caused by: java.lang.RuntimeException: bad array lengths
E/AndroidRuntime( 3868): at android.os.Parcel.readStringArray(Parcel.java:1125)
E/AndroidRuntime( 3868): at com.adins.msm.model.LookupCriteriaBean.<init>(LookupCriteriaBean.java:33)
E/AndroidRuntime( 3868): at com.adins.msm.model.LookupCriteriaBean$1.createFromParcel(LookupCriteriaBean.java:80)
E/AndroidRuntime( 3868): at com.adins.msm.model.LookupCriteriaBean$1.createFromParcel(LookupCriteriaBean.java:1)
E/AndroidRuntime( 3868): at android.os.Parcel.readParcelable(Parcel.java:2470)
E/AndroidRuntime( 3868): at android.os.Parcel.readValue(Parcel.java:2364)
E/AndroidRuntime( 3868): at android.os.Parcel.readListInternal(Parcel.java:2778)
E/AndroidRuntime( 3868): at android.os.Parcel.readArrayList(Parcel.java:2035)
E/AndroidRuntime( 3868): at android.os.Parcel.readValue(Parcel.java:2385)
E/AndroidRuntime( 3868): at android.os.Parcel.readArrayMapInternal(Parcel.java:2717)
E/AndroidRuntime( 3868): at android.os.BaseBundle.unparcel(BaseBundle.java:269)
E/AndroidRuntime( 3868): at android.os.Bundle.getParcelableArrayList(Bundle.java:886)
E/AndroidRuntime( 3868): at com.adins.msm.LookupActivity.initialize(LookupActivity.java:59)
E/AndroidRuntime( 3868): at com.adins.msm.LookupActivity.onCreate(LookupActivity.java:49)
E/AndroidRuntime( 3868): at android.app.Activity.performCreate(Activity.java:6662)
E/AndroidRuntime( 3868): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
E/AndroidRuntime( 3868): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
any help is appreciated
Here is code from my activity that has the button which triggers the error
public class LookupActivity extends Activity implements OnClickListener {
private ArrayAdapter<LookupCriteriaBean> listAdapter;
private String lovType;
public final LayoutParams defLayout = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
private QuestionBean bean = null;
private LinearLayout questionContainer;
private int totalCriteia = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lookup);
initialize();
//---change to portrait mode---
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
private void initialize() {
setClickListener();
Bundle extras = getIntent().getExtras();
ArrayList<LookupCriteriaBean> list = extras.getParcelableArrayList(
Global.BUND_KEY_LOV_CRITERIA);
listAdapter = new ArrayAdapter<LookupCriteriaBean>(this,
android.R.layout.simple_spinner_item, list);
listAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
bean = DynamicSurveyActivity.getQuestionInFocus();
lovType = bean.getAnswerType();
if(bean.getTextMaxLength()!=0){
totalCriteia = bean.getTextMaxLength();
}
questionContainer = (LinearLayout) findViewById(R.id.sub_search_bar);
questionContainer.setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < totalCriteia; i++) {
ViewGroup view = generateDropdownDesc(this,listAdapter, i);
questionContainer.addView(view, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
}
}
private void setClickListener() {
Button btnSearch = (Button) findViewById(R.id.search_button);
btnSearch.setOnClickListener(this);
}
public void onClick(View v) {
Button btn = (Button) v;
int id = btn.getId();
if (R.id.search_button == id) {
String lookupSearchValue = this.getSearchValue().trim();
// if (this.validateSearchValue(lookupSearchValue)) {
LookupCriteriaBean lookupCriteriaBean[] = new LookupCriteriaBean[totalCriteia];
for (int i = 0; i < totalCriteia; i++) {
LinearLayout qContainer = (LinearLayout) questionContainer.getChildAt(i);
Spinner spinnerCriteria = (Spinner) qContainer.getChildAt(0);
int posSpinner = spinnerCriteria.getSelectedItemPosition();
EditText editText = (EditText) qContainer.getChildAt(1);
LookupCriteriaBean beanCriteria = listAdapter.getItem(posSpinner);
beanCriteria.setLookupSearchValue(editText.getText().toString().trim());
lookupCriteriaBean[i] = beanCriteria;
}
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put(Global.MAP_KEY_LOOKUP_CRITERIA, mergeLookupCriteriaBean(lookupCriteriaBean));
if (Global.AT_LOV.equals(lovType)) {
new LookupResultTask(this, getString(R.string.progressWait))
.execute(paramMap);
}
else if (Global.AT_LOV_W_FILTER.equals(lovType)) {
LookupManager lookupManager = new LookupManager();
QuestionBean qBean = DynamicSurveyActivity.getQuestionInFocus();
List<QuestionBean> listOfQuestion = DynamicSurveyActivity.getListOfQuestion();
lookupManager.setFilterValue(listOfQuestion, qBean);
paramMap.put(Global.MAP_KEY_LOOKUP_FILTER, qBean.getLovFilters());
new LookupResultTask(this, getString(R.string.progressWait))
.execute();
}
// }
}
}
private String getSearchValue() {
String value = "";
for (int i = 0; i < totalCriteia; i++) {
LinearLayout qContainer = (LinearLayout) questionContainer.getChildAt(i);
EditText editText = (EditText) qContainer.getChildAt(1);
value = value+editText.getText().toString().trim();
}
return value;
}
private boolean validateSearchValue(String searchValue) {
boolean valid = true;
List<String> errMessage = new ArrayList<String>();
if ("".equals(searchValue)) {
errMessage.add(getString(R.string.lovHint) + " " + getString(R.string.msgRequired));
}
if (errMessage.size() > 0) {
valid = false;
String[] msg = (String[]) errMessage.toArray(new String[errMessage.size()]);
String alert = Tool.implode(msg, "\n");
Toast.makeText(this, alert, Toast.LENGTH_LONG).show();
}
return valid;
}
public LinearLayout generateDropdownDesc(Activity activity,
ArrayAdapter<LookupCriteriaBean> listAdapter, int pos) {
LinearLayout container = new LinearLayout(activity);
container.setOrientation(LinearLayout.VERTICAL);
int totalOption = listAdapter.getCount();
final String prompt = getString(R.string.lovCriteria);
Spinner spinner = new Spinner(activity);
EditText desc = new EditText(activity);
desc.setHint(string.lovHint);
spinner.setAdapter(listAdapter);
spinner.setPrompt(prompt);
if (pos < totalOption) {
spinner.setSelection(pos);
} else {
int tempPos = (pos%totalOption);
spinner.setSelection(tempPos);
}
container.addView(spinner, defLayout);
container.addView(desc, defLayout);
return container;
}
private LookupCriteriaBean mergeLookupCriteriaBean(LookupCriteriaBean[] lookupCriteriaBeanArray) {
LookupCriteriaBean lookupCriteriaBean = new LookupCriteriaBean();
lookupCriteriaBean.setLookupCode(lookupCriteriaBeanArray[0].getLookupCode());
lookupCriteriaBean.setLookupDisplayName(lookupCriteriaBeanArray[0].getLookupDisplayName());
lookupCriteriaBean.setLookupField(lookupCriteriaBeanArray[0].getLookupField());
lookupCriteriaBean.setLookupSearchValue(lookupCriteriaBeanArray[0].getLookupSearchValue());
if (lookupCriteriaBeanArray.length > 1) {
for (int i = 1; i < lookupCriteriaBeanArray.length; i++) {
String code = lookupCriteriaBean.getLookupCode();
String field = lookupCriteriaBean.getLookupField();
String searchValue = lookupCriteriaBean.getLookupSearchValue();
lookupCriteriaBean.setLookupCode(code
+ Global.DELIMETER_SUBSUBDATA
+ lookupCriteriaBeanArray[i].getLookupCode());
lookupCriteriaBean.setLookupField(field
+ Global.DELIMETER_SUBSUBDATA
+ lookupCriteriaBeanArray[i].getLookupField());
lookupCriteriaBean.setLookupSearchValue(searchValue
+ Global.DELIMETER_SUBSUBDATA
+ lookupCriteriaBeanArray[i].getLookupSearchValue());
}
}
return lookupCriteriaBean;
}
the button with R.id.search_button when pressed crashes on android 7 and up
hmmm... so i tried all sorts of things, even rewriting the code, still this problem persists, it might be something else in nougat that is causing this, any ideas?
after rewriting my code a few times ad referencing other answers with the same problem, splitting the array of string i used to seperate strings fixed this issue, althoug i still have no idea why getStringArray(arrS)
would crash only on android 7 and up.
i do wonder why my code still runs on lower versions fine though.
so both seperating all the fields and accessing them in the correct order then it works.
here is my fixed code:
---------------snip---------------------------------
public LookupCriteriaBean(Parcel in) {
lookupCode = in.readString();
lookupField = in.readString();
lookupDisplayName = in.readString();
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(lookupCode);
dest.writeString(lookupField);
dest.writeString(lookupDisplayName);
}
-----------------snip--------------------------------