问题
In my application I'm fetching inbox messages
from native application to my application
. Also there are checkboxes to select multiple messages.But the problem arises are no messages are displaying in listview while running code
and also showing error android.database.StaleDataException: Attempted to access a cursor after it has been closed.
ArrayAdapter<SMSListModel> adapter;
List<SMSListModel> list = new ArrayList<SMSListModel>();
TextView textViewSMSSender, textViewSMSBody
public void getInboxSms() {
//Uri message = Uri.parse("content://sms/inbox");
ContentResolver cr = getContentResolver();
c = cr.query(Uri.parse("content://sms/inbox"), null, null, null, null);
//startManagingCursor(c);
//totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < c.getCount(); i++) {
Log.d("SMSss", "Contact number : "+ c.getString(c.getColumnIndexOrThrow("address"))+ "\n"
+ "msg : " + c.getColumnIndexOrThrow("body")
+ "\n"
+ "Person : "
+ getContactName(getApplicationContext(),c.getString(c.getColumnIndexOrThrow("address"))));
c.moveToNext();
}
}
c.close();
}
public String getContactName(Context context, String phoneNumber) {
ContentResolver cr = context.getContentResolver();
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNumber));
Cursor cursor = cr.query(uri,
new String[] { PhoneLookup.DISPLAY_NAME }, null, null, null);
if (cursor == null) {
return null;
}
String contactName = null;
if (cursor.moveToFirst()) {
contactName = cursor.getString(cursor
.getColumnIndex(PhoneLookup.DISPLAY_NAME));
}
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
return contactName;
}
private List<SMSListModel> getModel()
{
if(c.getCount()>0)
{
for(int i=0;i<c.getCount();i++)
{
if(c.moveToPosition(i))
{
list.add(new SMSListModel(c.getString(c.getColumnIndex("address")),c.getString(c.getColumnIndex("body"))));
}
}
}
return list;
}
SmsListAdapter
public class SMSListAdapter extends ArrayAdapter<SMSListModel> {
private final List<SMSListModel> list;
private final Activity mContext;
boolean checkAll_flag = false;
boolean checkItem_flag = false;
public SMSListAdapter(Activity context,List<SMSListModel> list)
{
super(context, R.layout.listview_each_item, list);
Log.d("size of list", ""+list.size());
mContext = context;
this.list = list;
}
static class ViewHolder {
protected TextView textAddress;
protected TextView textBody;
protected CheckBox checkbox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflator = mContext.getLayoutInflater();
convertView = inflator.inflate(R.layout.listview_each_item, null);
viewHolder = new ViewHolder();
viewHolder.textAddress = (TextView) convertView.findViewById(R.id.tvSMSSend);
viewHolder.textBody = (TextView) convertView.findViewById(R.id.tvSMSBody);
viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.cbSelect);
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag.
list.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
}
});
convertView.setTag(viewHolder);
convertView.setTag(R.id.tvSMSSend, viewHolder.textAddress);
convertView.setTag(R.id.tvSMSBody, viewHolder.textBody);
convertView.setTag(R.id.cbSelect, viewHolder.checkbox);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.checkbox.setTag(position); // This line is important.
viewHolder.textAddress.setText(list.get(position).getAddress());
viewHolder.textBody.setText(list.get(position).getBody());
viewHolder.checkbox.setChecked(list.get(position).isSelected());
return convertView;
}}
SMSListModel
public class SMSListModel {
private String address;
String body;
private boolean selected;
public SMSListModel(String address, String body) {
this.address = address;
this.body = body;
}
public String getAddress() {
return address;
}
public String getBody() {
return body;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}}
回答1:
cursor "c" is a global variable which you use in these two methods
getModel();
getInboxSms();
But the problem is you close the cursor in getInboxSms()
method and try to access same cursor in getModel()
method.
So remove this line from getInboxSms() method and try.
c.close();
Update this method
private List<SMSListModel> getModel() {
if (c.getCount() > 0) {
c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
list.add(new SMSListModel(c.getString(c.getColumnIndex("address")), c.getString(c.getColumnIndex("body"))));
c.moveToNext();
}
}
return list;
}
Update your onCreate() Method
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = this;
listViewSMS = (ListView) findViewById(R.id.lvSMS);
getInboxSms();
textViewSMSSender = (TextView) findViewById(R.id.tvSMSSend);
textViewSMSBody = (TextView) findViewById(R.id.tvSMSBody);
smsListAdapter = new SMSListAdapter(this, getModel());
listViewSMS.setAdapter(smsListAdapter); // you forget to add this line
listViewSMS.setOnItemClickListener(this);
}
回答2:
Do not try to close the cursor in both your method that is
public String getContactName(Context context, String phoneNumber)
public void getInboxSms()
You can try to close the cursor when all your operations are completed
来源:https://stackoverflow.com/questions/23131866/error-attempted-to-access-a-cursor-after-it-has-been-closed