I installed the following code on my Android 2.2 phone and the sender's name shows as labuser for some messages when it is actually something else :-
public class SMSReaderActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView myListView = (ListView) findViewById(R.id.myListView);
final ArrayList<String> smses = new ArrayList<String>();
final ArrayAdapter<String> aa = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, smses);
myListView.setAdapter(aa);
Context context = getApplicationContext();
Cursor cursor = context.getContentResolver().query(
Uri.parse("content://sms/inbox"),
new String[] { "address", "person", "date", "body" }, null,
null, "date desc");
cursor.moveToFirst();
int count = cursor.getCount();
for (int j = 0; j < count; j++) {
String msg = cursor.getString(0) + ", " + cursor.getString(1)
+ ", " + cursor.getLong(2) + ", " + cursor.getString(3);
Log.w("SMS", "Read SMS:" + msg);
if (cursor.getString(3).indexOf("rbs") >= 0) {
smses.add(msg);
Log.w("SMS", "Added");
}
cursor.moveToNext();
}
cursor.close();
aa.notifyDataSetChanged();
}
labuser is not an a/c on my development machine and this happens with only matching smses. I cannot figure out the source of this.
Thanks
Himanshu
Giving it the READ_CONTACTS permission fixed it. That my app, reading SMS's without appropriate permissions, could screw up the default one was strange.
Related
I need to fetch out the list of contacts that are recently used in last 24 hours and most frequently used.
I have searched a lot but did not find any way to do that. I also come to know that google has revoked the URIs to get frequently used contacts : https://developer.android.com/reference/android/provider/ContactsContract.Contacts#CONTENT_FREQUENT_URI
But what is the substitute of this URI is not given?
Please let me know the ways to achieve:
Fetch list of contacts contacted recently in last 24 hours.
Fetch the top 3 most frequently used contacts.
The whole point of deprecating the CONTENT_FREQUENT_URI as well as the TIMES_CONTACTED and LAST_TIME_CONTACTED fields in the Contacts table are to prevent apps from accessing the information you're looking for.
Google now considers this info to be sensitive user info, and will not allow apps to obtain that going forward.
However, from my experience, it seems that all devices I know of or are used by our users still allow access to the deprecated API, so if you need something that will be ok for most of your users within the next year or so, you can still use it.
Code should be something like:
String[] projection = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.LAST_TIME_CONTACTED };
Cursor lastContacted = getContentResolver().query(Contacts.CONTENT_URI, projection, Contacts.LAST_TIME_CONTACTED + " < " + lastDayTimestamp, null, Contacts.LAST_TIME_CONTACTED + " DESC");
DatabaseUtils.dumpCursor(lastContacted);
Cursor mostContacted = getContentResolver().query(Contacts.CONTENT_URI, projection, null, null, Contacts.TIMES_CONTACTED + " DESC");
DatabaseUtils.dumpCursor(mostContacted); // might want to limit this to 3
public class MainActivity extends AppCompatActivity {
ListView listView ;
ArrayList<String> StoreContacts ;
ArrayAdapter<String> arrayAdapter ;
Cursor cursor ;
String name, phonenumber ;
public static final int RequestPermissionCode = 1 ;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView)findViewById(R.id.listview1);
button = (Button)findViewById(R.id.button1);
StoreContacts = new ArrayList<String>();
EnableRuntimePermission();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
GetContactsIntoArrayList();
arrayAdapter = new ArrayAdapter<String>(
MainActivity.this,
R.layout.contact_items_listview,
R.id.textView, StoreContacts
);
listView.setAdapter(arrayAdapter);
}
});
}
public void GetContactsIntoArrayList(){
cursor =
getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,null, null, null);
while (cursor.moveToNext()) {
name =
cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAM
E));
phonenumber =
cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.NUMBER));
StoreContacts.add(name + " " + ":" + " " + phonenumber);
}
cursor.close();
}
public void EnableRuntimePermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(
MainActivity.this,
Manifest.permission.READ_CONTACTS))
{
Toast.makeText(MainActivity.this,"CONTACTS permission allows us to Access
CONTACTS app", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{
Manifest.permission.READ_CONTACTS}, RequestPermissionCode);
}
}
#Override
public void onRequestPermissionsResult(int RC, String per[], int[] PResult) {
switch (RC) {
case RequestPermissionCode:
if (PResult.length > 0 && PResult[0] ==
PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this,"Permission Granted, Now your
application can access CONTACTS.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this,"Permission Canceled, Now your
application cannot access CONTACTS.", Toast.LENGTH_LONG).show();
}
break;
}
}
}
I have two AutoCompleteTextViews that are populated with data from sqlite database. I pull information from an ERP Server and store it locally in the sqlite database and populate the textview like in this:
equipment = (AutoCompleteTextView) findViewById(R.id.equipmentAutoCompleteTextView);
if(equipment.getText().toString().length() == 0){
equipment.setError("Equipment is required");
}
FieldInstallationDB sqlitedb1 = new FieldInstallationDB(this);
sqlitedb1.openForRead();
String[] items = sqlitedb.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
ArrayAdapter<String> adapter1 = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, items);
equipment.setAdapter(adapter1);
equipment.setThreshold(1);
And here:
customerName = (AutoCompleteTextView) findViewById(R.id.customerNameAutoCompleteTextView);
if(customerName.getText().toString().length() == 0){
customerName.setError("Customer Name is required");
}
FieldInstallationDB sqlitedb = new FieldInstallationDB(this);
sqlitedb.openForRead();
String[] accounts = sqlitedb.getAllCustNames();
for(int i = 0; i < accounts.length; i++)
{
Log.i(this.toString(), accounts[i]);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, accounts);
customerName.setAdapter(adapter);
customerName.setThreshold(1);
Assuming I have these:
Black Spoon
Red Spoon
Spoonful
And I start typying "spo", I want to see all three items listed to make a selection. Instead, I get only "Spoonful" coming up. How do I get it to recognise and display all instances(items) that have the letters "spo"?
UPDATE:
After the first comment to my question, I read more articles and updated my code to look like this:
equipment = (AutoCompleteTextView) findViewById(R.id.equipmentAutoCompleteTextView);
if(equipment.getText().toString().length() == 0){
equipment.setError("Equipment is required");
}
FieldInstallationDB sqlitedb1 = new FieldInstallationDB(this);
sqlitedb1.openForRead();
String[] items = sqlitedb1.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
equipment.setThreshold(1);
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, items, toView, 0);
itemNameAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return suggestItemCompletions(constraint);
}
});
itemNameAdapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
public CharSequence convertToString(Cursor cur) {
int index = cur.getColumnIndex(FieldInstallationDB.ITEM_NAME);
return cur.getString(index);
}});
equipment.setAdapter(itemNameAdapter);
Here is the suggestitemcompletions method written in the activity class:
public Cursor suggestItemCompletions(CharSequence str) {
return getContentResolver().query(null, new String[] {FieldInstallationDB.ITEM_NAME}, "(" + FieldInstallationDB.ITEM_NAME + " LIKE ? ", new String[] {"%" + str + "%"}, null);
}
This suggests to use getContentResolver() which does not make sense in my case since I am accessing the database of my application and not of another application. As a result it does not work because I set the URI parameter to null since my database table has no URI. However, if i decide not to use getContentResolver() and query the FieldInstallationDB directly, I get the error at .query() saying cannot resolve method.
UPDATE II:
I used rawQuery() as suggested and it works:
public Cursor suggestItemCompletions(CharSequence str) {
fieldInstDatabase = openForRead();
String sql = "Select "+ ITEM_NAME+ " FROM "+ TABLE_EQUIPMENT+ " WHERE "+ ITEM_NAME + " LIKE ?";
String[] selectArgs = new String[]{ "%" + str + "%"};
return fieldInstDatabase.rawQuery(sql,selectArgs);
}
This method is in my db class and I am calling it in main activity here:
itemNameAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return sqlitedb1.suggestItemCompletions(constraint);
}
});
This is working except that I am getting an IllegalArgumentException here:
01-10 13:07:08.792 5361-5361/com.example.sweetiean.stlfieldinstallation1 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sweetiean.stlfieldinstallation1, PID: 5361
java.lang.IllegalArgumentException: column 'Bag(TypeC) :
5900016009' does not exist
which makes sense because "Bag(TypeC) :
5900016009" is not a column, it is the first item in the ITEM NAME column in the database.
I do not know why it is reading the first item as the column name. I have tried to debug but I cannot step into
public Cursor runQuery(CharSequence constraint) {
return sqlitedb1.suggestItemCompletions(constraint);
}
As suggested in the comments, an IllegalArgumentException is occurring here because of the from parameter in my SimpleCursorAdapter. The from and to parameters of the SimpleCursorAdapter require the column name of the table and the textview to populate respectively.
In my case, I was populating the from parameter with a string array of the items I was getting from the database:
String[] items = sqlitedb1.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
equipment.setThreshold(1);
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, items, toView, 0);
Correcting it to:
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, fromCol, toView, 0);
With fromCol defined as final static String[] fromCol = new String[] { FieldInstallationDB.ITEM_NAME }; fixed it.
I have implemented a code which gets me the first sms from "Sent SMS" in string format.
I want to get all the sms from the sent box one by one starting from the first.
I would like to save them in SQLite database.
The below code shows the first sent sms in Toast but how do i get all the sent sms?
public class MainActivity extends Activity {
String address, name, date, msg, type;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn =(Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Uri mSmsinboxQueryUri = Uri.parse("content://sms/sent");
Cursor cursor1 = getContentResolver().query(mSmsinboxQueryUri,
new String[] { "_id", "thread_id", "address", "person", "date",
"body", "type" }, null, null, null);
startManagingCursor(cursor1);
String[] columns = new String[] { "address", "person", "date", "body","type" };
if (cursor1.getCount() > 0) {
String count = Integer.toString(cursor1.getCount());
//Log.e("Count",count);
System.out.println("Count:" + count);
while (cursor1.moveToNext()){
address = cursor1.getString(cursor1.getColumnIndex(columns[0]));
name = cursor1.getString(cursor1.getColumnIndex(columns[1]));
date = cursor1.getString(cursor1.getColumnIndex(columns[2]));
msg = cursor1.getString(cursor1.getColumnIndex(columns[3]));
type = cursor1.getString(cursor1.getColumnIndex(columns[4]));
}
}
Toast.makeText(getApplicationContext(), address + "\n" + name + "\n" + date + "\n" + msg + "\n" + type, Toast.LENGTH_LONG).show();
}
});
}
}
use
cursor.moveToFirst();
before line
while (cursor1.moveToNext())
instead of while use
if(cursor1.moveToFirst())
{
for (int i = 0; i <cursor1.getCount(); i++)
{
address = cursor1.getString(cursor1.getColumnIndex(columns[0]));
name = cursor1.getString(cursor1.getColumnIndex(columns[1]));
date = cursor1.getString(cursor1.getColumnIndex(columns[2]));
msg = cursor1.getString(cursor1.getColumnIndex(columns[3]));
type = cursor1.getString(cursor1.getColumnIndex(columns[4]));
cursor1.moveToNext();
}
}
and also close cursor at end
I am using 2.1 platform.Trying to retrieve all the SMS from the Emulator. No Compile error, NO Logcat Error in my code.I included the permission for ReadSMS in manifest file.When I run the code no display in the ListView. In my XML file there is only one ListView. On that ListView I am trying to display all the SMS of format ( Number : Sms Body) from the Emulator.
Code
public class SMSActivity extends Activity {
/** Called when the activity is first created. */
ListView lview;
String Body = "" ;
int Number;
ArrayList<String> smslist=new ArrayList<String>();
ArrayAdapter<String> itemAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lview =(ListView)findViewById(R.id.lv);
itemAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,smslist);
lview.setAdapter(itemAdapter);
ContentResolver cr = getContentResolver();
Cursor c = cr.query(Uri.parse("content://sms/"), new String[] { "_id", "address", "date", "body","read" },"_id = "+null, null, null);
while(c.moveToNext()){
Number = c.getInt(c.getColumnIndexOrThrow("address"));
Body = c.getString(c.getColumnIndexOrThrow("body")).toString();
smslist.add( Number + "\n" + Body);
}
itemAdapter.notifyDataSetChanged();
c.close();
}
}
How to solve this problem ?
The error you are doing is you just mentioning that you want to read sms but you forgot to say
from which folder you need them.e.g from inbox,outbox etc..
If you need to read SMS from inbox use following.
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
You can also query column names using
for (int i = 0; i < cursor.getColumnCount(); i++) {
Log.i("info", cursor.getColumnName(i));
}
Below is a my Contact_Picker class. I am going to be using this class to create a list of contacts with checkboxes, giving the user the option to select multiple contacts from their phonebook. I have a layout xml that I am using that has 2 buttons at the bottom: Clear All and Done.
When 'Done' is pressed, I need it to get all of the names that are checked, and save them in a list/preferences file. Right now, I can find what POSITIONS are checked, but I don't know how to retrieve the corresponding information associated with them (the name/phone number of the selected contact). I have searched for days on a method that will work, and have not come up with anything. Any code/pseudo code/ideas are greatly appreciated.
Contact_Picker Class:
public class Contact_Picker extends ListActivity {
protected static final String TAG = null;
public String[] Contacts = {};
public int[] to = {};
public ListView myListView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contacts_list);
final Button done_Button = (Button) findViewById(R.id.done_Button);
final Button clear_Button =(Button) findViewById(R.id.clear_Button);
Cursor mCursor = getContacts();
startManagingCursor(mCursor);
ListAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_multiple_choice, mCursor,
Contacts = new String[] {ContactsContract.Contacts.DISPLAY_NAME },
to = new int[] { android.R.id.text1 });
setListAdapter(adapter);
myListView = getListView();
myListView.setItemsCanFocus(false);
myListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
clear_Button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"Selections Cleared", Toast.LENGTH_SHORT).show();
ClearSelections();
}
});
/** When 'Done' Button Pushed: **/
done_Button.setOnClickListener(new View.OnClickListener() {
public void onClick (View v){
Log.i(TAG,":Done Button Selected:");
SparseBooleanArray checkedPositions = myListView.getCheckedItemPositions();
Log.i(TAG,"Number of Checked Positions: " + checkedPositions.size());
if (checkedPositions != null)
{
int count = myListView.getCount();
for ( int i=0;i<count;i++)
{
Log.i(TAG,"Selected items: " + checkedPositions.get(i));
}
}
}
}); //<-- End of Done_Button
} //<-- end of onCreate();
private void ClearSelections() {
int count = this.myListView.getAdapter().getCount();
for (int i = 0; i < count; i++) {
this.myListView.setItemChecked(i, false);
}
}
private Cursor getContacts() {
// Run query
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '"
+ ("1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs,
sortOrder);
} //<-- end of getContacts();
}
Will Create Output Such As:
Sele02-12 01:25:09.733: INFO/(219): :Done Button Selected:
02-12 01:25:09.743: INFO/(219): Number of Checked Positions: 2
02-12 01:25:09.743: INFO/(219): Selected items: true
02-12 01:25:09.743: INFO/(219): Selected items: false
02-12 01:25:09.743: INFO/(219): Selected items: true
02-12 01:25:09.752: INFO/(219): Selected items: false
see this
public String[] getlistcontacts() {
// TODO Auto-generated method stub
int i=0;
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null,null, null, null);
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null , null);
int a= cur.getCount();
String[] cttlist=new String[a+1];
cur.moveToFirst();
pCur.moveToFirst();
for (int j=0; j<a;j++){
int nm=cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
//int nb=pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String name=cur.getString(nm);
int nb=pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number=pCur.getString(nb);
cttlist[i]=name.concat("<;>").concat(number);
//Toast.makeText(PizzastimeActivity.this, "alkamkljziha"+name+":"+number, Toast.LENGTH_LONG).show();
i++;
cur.moveToNext();
pCur.moveToNext();
}
return cttlist;
}
in this code i tried to get list of contact in a table of string then u can use it easily
Here is a correct approach:
SparseBooleanArray selectedPositions = listView.getCheckedItemPositions();
for (int i=0; i<selectedPositions.size(); i++) {
if (selectedPositions.get(selectedPositions.keyAt(i)) == true) {
//do stuff
}
}
maybe you can manually keep track of your contacts:
Vector<String> names=new Vector<String>();
private Cursor getContacts() {...
Cursor cur = managedQuery(uri, projection, selection, selectionArgs,
sortOrder);
int col = cur.getColumnIndex("display_name");
while(cur.moveToNext())
names.add(cur.getString(col));
cur.moveToFirst();
return cur;
}
and then output them synchronously:
for ( int i=0;i<count;i++)
{
Log.i(TAG,"Selected items: " + checkedPositions.get(i));
Log.i(TAG,"Selected name: " + names.get(i));
}
I forgot about this post until Team Pannous left an answer. I'm sure that their method would work, but I ended up using this instead:
SparseBooleanArray checked = myListView.getCheckedItemPositions();
for (int i = 0; i < ContactsList.length; i++) {
Log.v(TAG, ContactsList[i] + ": " + checked.get(i)); //<-- Will print every contact with 'true'
if (checked.get(i) == true) {
Object o = getListAdapter().getItem(i);
String name = o.toString();
WriteSettings(self, name);
}
}
Just in case anyone else is having a problem with a multiple-choice listview.