This might be a stretch, but I was wondering if it is possible to add functionality to an application that is already created for the android device. Specifically, I would like to send a broadcast whenever the user tries to make a new search in the internet browser. There might be another way to act only when the user searches the browser, but I thought this would be the easiest. If this isn't possible (or is completely the wrong way of going about this), please let me know. Any help is appreciated.
You can probably query the Browser provider and get search data from it. Here is some basic code on how to do it:
Cursor cursor = this.context.getContentResolver().query(Browser.SEARCHES_URI, null, null, null, null);
if (cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
final int indexDate = cursor.getColumnIndex(Browser.SearchColumns.DATE);
final int indexTerm = cursor.getColumnIndex(Browser.SearchColumns.SEARCH);
String date = cursor.getString(indexDate);
String term = cursor.getString(indexTerm);
cursor.moveToNext();
}
}
cursor.close();
Keep in mind that it would be better if you run queries on a separate Thread using the Loader framework.
I do not think there is a broadcast sent when a new search is performed.
Related
I am creating an AutoCompleteTextView field on a form that I want to possibly populate with a matching selection from the CONTACTS email addresses.
Doing some searching, I was able to find some older examples on here (that have alot of depreciated code... nothing newer) but with some trial and error I was able to get it to work matching the first characters of the email address as I type... although I don't have a 100% understanding of exactly how this works.
What I would really like to do is have it show ANY match ANYWHERE in the email addresses on file. That is, if I type gma, I would like it to show: gmartin#xyz.com, gregmaster#yahoo.com, jim#gmail.com, sam#gmail.com, etc.
As I understand it, I need to use a LIKE command in the query. But no matter how I format it, I get the same results... only matches the start of the email address.
Here is my current code attempt with the LIKE....
ArrayList<String> emailAddressCollection = new ArrayList<String>();
ContentResolver cr = getContentResolver();
String[] projection={ContactsContract.CommonDataKinds.Email.DATA};
Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, ContactsContract.CommonDataKinds.Email.ADDRESS + " LIKE '%A%'", null, null);
while (emailCur.moveToNext())
{
String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
emailAddressCollection.add(email);
}
emailCur.close();
String[] emailAddresses = new String[emailAddressCollection.size()];
emailAddressCollection.toArray(emailAddresses);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, emailAddresses);
AutoCompleteTextView actextView = (AutoCompleteTextView)findViewById(idTo);
actextView.setAdapter(adapter);
Any idea what I am missing here?
Also, another somewhat related question, in my dropdownlist, i would like to show the email address match plus the NAME listed in that record... and just return the email address when selected.
Can this be accomplished using this code or do I need to look at something else?
AutoCompleteTextView is designed by default to match based ONLY on the starting characters. So the gma in sam#gmail.com will not be recognized. You can implement your own widget which does a lookup based on the 'LIKE' criteria. Android only searches through the first few characters for each entry in the adapter elements.
If you must choose to search by 'LIKE' criteria, it is possible although it would be quite a task in itself. You could simply search by whether the string contains the text and then choose to filter by that - no need to query everytime. Alternatively, you could try searching for a library which does this.
I'm trying to tally the number of outgoing SMSes sent by the user. Currently, my code goes like this:
class SentSMSObserver extends ContentObserver {
....
}
SentSMSObserver sso = new SentSMSObserver(new Handler());
ContentResolver cr = this.getContentResolver();
cr.registerContentObserver(Uri.parse("content://sms"), true, sso);
I tried to run the app in an emulator sporting Jelly Bean and for some reason, when I send a text message via the native SMS app, it increments my tally by three.
Now, I decided to replace content://sms with content://sms/sent as the related StackOverflow q&a's would suggest, but when I run the app with that setting, it never even executes my content observer's onChange(). What do I do?
the callback on registerContentObserver will be called when the db updater calls the exact uri for which you have registered. But in your case the MMS app does not use content://sms/sent but uses something like content://sms/10 and keeps moving it from type QUEUED to OUTBOX and then to SENT . So i guess thats why you are recieving 3 updates when you register for content://sms/
MMS App changes the TYPE column each time after it is queued.
One way to solve this problem is each time you get the content change callback query for the uri and then get "type" column and check if its value is Telephony.Sms.MESSAGE_TYPE_SENT .
From the answer suggested by Lalit Poptani, you need to get the value of the "type" of record the cursor is currently pointing at.
// cr is the content resolver
Cursor cursor = cr.query(Uri.parse("content://sms"), null, null, null, null);
int columnIndex = cursor.getColumnIndex("type");
while (cursor.moveToNext()) {
int type = cursor.getInt(columnIndex);
if (type == 2) {
// do your stuff here
}
}
As mentioned in my discussion with nandeesh, the message types are not part of the public API, but they can be found here.
Currently, I'm fixing a bug where Android makes inaccurate counts of a single sent SMS message when it is directed to more than one recipient (sending to two people counts three, sending to three counts 5). It seems that even when you filter out the message types, the content observer gets invoked more than once even for just a single message. I will post updates to this answer when I've fixed it.
I need to be able to select multiple contacts in Android. The flow is like this :
User clicks on a button which opens the Contacts application.
However, instead of being able to select a single contact, I need to be able to select multiple contacts (in the same launch of the intent).
If a contact has multiple phone numbers, I need the user to be able to choose which phone number he wants to select.
This feature is already present in my Samsung Android Phone (Running 2.3 Gingerbread) when I click on "Contacts" in the Messaging app. See screenshot below :
There is not built in way of doing this, so you need to do most of the work by yourself. Luckily, it's not that hard.
Display
To Display your contacts you can use either a listview with the multi-select choice mode, or you can create a custom adapter and bind it to a regular listview. I don't think the listview with multi-select will let you put anything other than text for each row, but you'd have to dig deeper to find out.
I've used the custom adapter method for something very similar (except the multiple phone numbers part). It's pretty easy to do and I find custom adapters are really useful in the long run.
Custom Adapter Listview Tutorial
With a custom adapter setup, you can create data objects with all the information for a person including their Name and Phone Number(s). In the getView of your Custom Adapter, you can decide what/how and where to display each piece of information.
Gathering Information
You'll need to use the ContactContract API to get information for your contacts.
Reading Contact Info
Reading ALL phone numbers for a Contact
You will have to write this all yourself. You can use the ContactsContract provider to query for all contacts with phone numbers, and then for the selected contact you can query for all phone numbers for that contact. You can display the results in activities or dialogs as you see fit.
Unfortunately this code isn't supported for all versions of android
I know it's kinda late but wanted to share this!
I found some incomplete code in the net and after cracking my head with it I finally found the answer!
Basically you launch the picker and let it return the data in the extras =]
There was no full answer in the net so hope it helps to some soul out there!
Enjoy:
public void pickContact(View v){
try {
Intent phonebookIntent = new Intent("intent.action.INTERACTION_TOPMENU");
phonebookIntent.putExtra("additional", "phone-multi");
startActivityForResult(phonebookIntent, PICK_CONTACT);
// PICK_CONTACT IS JUST AN INT HOLDING SOME NUMBER OF YOUR CHOICE
} catch (Exception e) {
e.printStackTrace();
}
}
public String getData(String contact, int which)
{
return contact.split(";")[which];
}
public void onActivityResult(int reqCode, int resultCode, Intent data) {
final int URI = 0;
final int NUMBER = 1;
if (RESULT_OK != resultCode) return;
Bundle contactUri = data.getExtras();
if (null == contactUri) return;
ArrayList<String> contacts = (ArrayList<String>)contactUri.get("result");
Toast.makeText(getApplicationContext(), getData(contacts.get(0),NUMBER), Toast.LENGTH_SHORT).show();
}
I've been working on a small media player app for Android. I'm having some trouble retrieving the meta data from the music files. I've been using the MediaMetadataRetriever, but it has proved to be quite troublesome. Does anyone know of a better way to go about this? If so how would one implement such method?
I've used JAudioTagger, which you can find here. It supports (basically) every version of ID3, so you're covered even for old files with outdated metadata. Pretty good (and easy) solution. Other options include mp3agic and entagged.
I was able to read the metadata from the Android database, using the code here. Just change the managedquery to something like:
String selection = MediaStore.Audio.Media.DATA + " == ?";
cursor = this.managedQuery(media,
projection,
selection,
new String[] {file.getCanonicalPath().toString()},
null);
This returns a cursor to the metadata of file. (Author, Title, duration etc.)
I'm currently making an SMS viewing application and using the ContentResolver to obtain all SMS messages on the phone (Yes, I understand the risks). Like other applications, I want to group all messages from the same person to one thread, display the latest message from them, and order the contacts by date of the last message.
When it comes to the address values of the incoming messages, they all contain the country code (e.g. +44123456789). But when the user saves his contacts, he could ignore the country code and simply type in the local format. So all outgoing messages are stored as 0123456789.
So, the database will contain the same address in both formats, +44123456789 and 0123456789. How do you match this 2 and remove the duplicate address?
Note:
1) Messages from the same person may not have the same "thread id"
2) There may not be a "contact id"/"display name" value for the address
Actually, messages to and from the same contact are in the same thread, therefore they have the same thread_id. (Apart from multiple recipient messages, which are in their own thread).
By looking in content://sms and storing a list of obtained thread_ids you can make sure there's no duplicates. With the address value you can use the following code to obtain the Display name.
Now, I'm trying to optimise this:
private String quickCallerId(String phoneNumber){
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
ContentResolver resolver=getContentResolver();
Cursor cur = resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME}, null, null, null);
if(cur!=null&&cur.moveToFirst()){
String value=cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME));
if(value!=null){
cur.close();
return value;
}
}
cur.close();
return "";
}
I don't have the code on me, but it's pretty easy to parse a string from right to left. You could do this and simply set an arbitrary limit on how accurate it must be to stop.
For instance (pseudo-code), given 2 strings (string1 and string2):
if first-char = '+'
len = 9
else
len = length(string1)
end
len = min(len, length(string2))
match = true
for i = len to 1
if substr( string2, i, 1) != substr( string2, i, 1)
match = false
quit
end
i--
end
You could get fancier by checking the characters immediately following the '+' sign to determine the country code, which would let you know how long that country's phone numbers are likely to be.
You would also need to check for people entering numbers as e.g. '(123) 456-7890 x1234' if that's a possibility. So it might be simpler to use some regexp variant...
Rory