I'm making a SMS app, I have a contact list, I want to be able to tap on contact and pass that contact number into new activity so that I could send message to that contact number,
I know How can we pass Value of clicked List item to new Activity, but somehow I'm not able to use that Intent.putExtra method in my scenario.
private void getContactList() {
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0) {
while (cur != null && cur.moveToNext()) {
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
if (cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] {
id
},
null);
while (pCur.moveToNext()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.i(TAG, "Name: " + name);
Log.i(TAG, "Phone Number: " + phoneNo);
}
pCur.close();
}
}
}
if (cur != null) {
cur.close();
}
}
You can use a Bundle to do this. You mentioned that you somehow couldn't call putExtra on your intent, make sure it isn't a typo as it is supposed to be putExtras, also make sure you are creating your intent correctly as shown below.
In the activity that will send the data:
Intent intent = new Intent(getActivity(), SecondActivity.class);
Bundle bundle = new Bundle();
bundle.putString("phoneNo", phoneNo);
intent.putExtras(bundle);
startActivity(intent);
Then on the receiving activity:
Bundle bundle = getIntent().getExtras();
String number = bundle.getString("phoneNo");
Related
Right now we have an app where we (after permissions) lookup a contact, and if they exist, display their contact card. However the lookup seems very inefficient, it loops through everyone, doesn't seem right. Is there a better query contacts db to lookup ONLY contacts that have an email address that we need?
Current Code Below (not efficient):
public static void showCardIfPossible(String email, Context context) {
Long contactId = lookupByEmail(email, context);
if (contactId != null) {
viewCardFor(context, contactId);
}
}
public static Long lookupByEmail(String email, Context context) {
Long contactId = null;
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (cursor == null || cursor.getCount() == 0) {
return null;
}
while (cursor.moveToNext())
{
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Cursor cur1 = cr.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
new String[]{id}, null);
if (cur1 != null && cur1.getCount() > 0) {
while (cur1.moveToNext()) {
//to get the contact names
String contactName=cur1.getString(cur1.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String contactEmail = cur1.getString(cur1.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
if(email.equals(contactEmail) || email.equals(contactName)){
contactId = Long.valueOf(id);
}
}
cur1.close();
}
}
cursor.close();
return contactId;
}
public static void viewCardFor(Context context, long contactId) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactId));
intent.setData(uri);
context.startActivity(intent);
}
Yes, you can just query directly on the Email.CONTENT_URI and using selection to find the right contact:
public static Long lookupByEmail(String email, Context context) {
ContentResolver cr = context.getContentResolver();
Long contactId = null;
String[] projection = new String[] { Email.CONTACT_ID };
String selection = Email.ADDRESS + "='" + email + "'";
Cursor cur = cr.query(Email.CONTENT_URI, projection, selection, null, null);
if (cur != null) {
if (cur.moveToFirst()) {
contactId = cur.getLong(0);
}
cur.close();
}
return contactId;
}
i need get contact number from contacts
i use below code for get contact number in onCreate:
buttonSelectContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);
}
});
and use below code in onAcivityResult:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri contactData = data.getData();
Cursor c = managedQuery(contactData, null, null, null, null);
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
String number = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER));
etName.setText(name);
etNumber.setText(number);
}
etName set correctly but etNumber is wrong,The values are 0 or 1 inside it
how to set contact number in etNumber??
here is how I have it in onActivityResult it gets all the phone numbers from a contact this is in a fragment so you will have to take out getActivity() if you are doing it from an activity
Uri contactData = data.getData();
Cursor c = getActivity().getContentResolver().query(contactData, null, null, null, null);
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
textcontact.setText(name + "\n");
customerName = name;
String contactId = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
String hasNumber = c.getString(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
String num = "";
if (Integer.valueOf(hasNumber) == 1) {
Cursor numbers = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
while (numbers.moveToNext()) {
num = numbers.getString(numbers.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
textcontact.append(num + "\n");
phoneNumbers.add(num);
}
}
}
I have an AutoCompleteTextView, which shows dropdown list of suggestions taken from a SQLiteDatabase query. At the moment it uses SimpleCursorAdapter, however there are several problems with it (I have a separate question about the issue here: SimpleCursorAdapter issue - "java.lang.IllegalStateException: trying to requery an already closed cursor").
Nevertheless, I was advised to look in the direction of CursorLoader and LoaderManager, and I've tried it, yet couldn't make it work. I'd be grateful if someone would guide/recommend/show the right way of migrating my code below to CursorLoader/LoaderManager concept. Any kind of help very appreciated!
mAdapter = new SimpleCursorAdapter(this,
R.layout.dropdown_text,
null,
new String[]{CITY_COUNTRY_NAME},
new int[]{R.id.text}, 0);
mAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
cityCountryName = cursor.getString(cursor.getColumnIndexOrThrow(CITY_COUNTRY_NAME));
mAutoCompleteTextView.setText(cityCountryName);
JSONWeatherTask task = new JSONWeatherTask();
task.execute(new String[]{cityCountryName});
}
});
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence sequence) {
String constraint = sequence.toString();
String queryString = "SELECT " + ID + ", " + CITY_ID + ", " + CITY_COUNTRY_NAME + " FROM " + TABLE_1;
constraint = constraint.trim() + "%";
queryString += " WHERE " + CITY_COUNTRY_NAME + " LIKE ?";
String params[] = {constraint};
try {
Cursor cursor = database.rawQuery(queryString, params);
if (cursor != null) {
startManagingCursor(cursor);
cursor.moveToFirst();
return cursor;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
});
mAutoCompleteTextView.setAdapter(mAdapter);
Here is the whole project for the reference (you can make a pull request there, if you wish): Open Weather App
Unfortunately, here on SO nobody came up with a solution, yet a colleague (he doesn't have an SO account) made a pull request with the migration fixes. It works perfectly, and I decided to post the correct answer here as well.
If you're interested in how these improvements look inside the actual code, you're welcome to visit the original open source project page on GitHub: Open Weather App
This is the new adapter:
mAdapter = new SimpleCursorAdapter(this,
R.layout.dropdown_text,
null,
new String[]{CITY_COUNTRY_NAME},
new int[]{R.id.text},0);
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
if (constraint != null) {
if (constraint.length() >= 3 && !TextUtils.isEmpty(constraint)) {
Bundle bundle = new Bundle();
String query = charArrayUpperCaser(constraint);
bundle.putString(CITY_ARGS, query);
getLoaderManager().restartLoader(0, bundle, MainActivity.this).forceLoad();
}
}
return null;
}
});
This is the onCreateLoader() callback:
#Override
public android.content.Loader<Cursor> onCreateLoader(int id, Bundle args) {
String s = args.getString(CITY_ARGS);
WeatherCursorLoader loader = null;
if (s != null && !TextUtils.isEmpty(s)) {
loader = new WeatherCursorLoader(this, database, s);
}
return loader;
}
Custom CursorLoader itself:
private static class WeatherCursorLoader extends CursorLoader {
private SQLiteDatabase mSQLiteDatabase;
private String mQuery;
WeatherCursorLoader(Context context, SQLiteDatabase cDatabase, String s) {
super(context);
mSQLiteDatabase = cDatabase;
mQuery = s + "%";
Log.d(TAG, "WeatherCursorLoader: " + mQuery);
}
#Override
public Cursor loadInBackground() {
return mSQLiteDatabase.query(TABLE_1, mProjection,
CITY_COUNTRY_NAME + " like ?", new String[] {mQuery},
null, null, null, "50");
}
}
This question already has answers here:
Unfortunately MyApp has stopped. How can I solve this?
(23 answers)
Closed 6 years ago.
When I search for data in my database, my app forced to stop. It is only happening when there are more than 2 rows, otherwise it's fine. I can insert data well. How can I solve this?
//click event
public void OnButtonClick(View v) {
dbhelper.open();
EditText a = (EditText)findViewById(R.id.user_tf);
String User_Name = a.getText().toString();
EditText b = (EditText)findViewById(R.id.password_tf);
String Password = b.getText().toString();
sqlitedatabase = dbhelper.getReadableDatabase();
String password = dbhelper.searchpass(User_Name);
if(Password.equals(password)) {
Toast.makeText(getBaseContext(), "User and pass correct", Toast.LENGTH_LONG).show();
dbhelper.close();
Intent intent = new Intent(Login_activity.this, Homepage.class);
startActivity(intent);
} else {
Toast.makeText(getBaseContext(),"User or pass incorrect", Toast.LENGTH_LONG).show();
dbhelper.close();
Intent intent = new Intent(Login_activity.this, Login_activity.class);
startActivity(intent);
}
// Searchpass in DBHelper class
public String searchpass(String user_name) {
db.isOpen();
db = this.getReadableDatabase();
String query = "SELECT " + UserConstruct.newUserinfo.UserName + ", " + UserConstruct.newUserinfo.Password + " FROM " + UserConstruct.newUserinfo.TableName + " ";
// int a = query.length();
Cursor cursor = db.rawQuery(query, null);
String a, b;
b = "not found";
do {
if (cursor.moveToFirst()) {
a = cursor.getString(0);
if (a.equals(user_name)) {
b = cursor.getString(1);
}
}
} while (cursor.moveToNext());
return b;
}
In this your are using both cursor.moveToNext and cursor.movetoFirst both. I don't think you should do both. use one that is cursor.moveToNext
while (cursor.moveToNext()) {
a = cursor.getString(0);
if (a.equals(user_name)) {
b = cursor.getString(1);
}
}
I followed a guide to enter the in app purchase and unlock all features. The procedure to purchase works well.
I explain what I do: I added a check in my database, which counts the number of records in a table, if the number is> = 1, I open an activity for purchase in the app. Once purchased, through the method getPurchases, control the purchase, if it was done I open the activity, otherwise I open the activity for purchase. I created this code peril control but I get error:
08-11 18:08:18.120: W/ContextImpl(19293): Implicit intents with startService
are not safe: Intent {
act=com.android.vending.billing.InAppBillingService.BIND }
android.content.ContextWrapper.bindService:529
main.Elenco_F_Fragment.Controlla_record_per_acquisto:243
main.Elenco_F_Fragment.access$9:233
this is the row 243:
final boolean blnBind = getActivity().bindService(new Intent(
"com.android.vending.billing.InAppBillingService.BIND"),
mServiceConn, Context.BIND_AUTO_CREATE);
this is the code for the control
private void Controlla_record_per_acquisto(){
SQLiteDatabase db = new DatabaseHelper(getActivity()).getReadableDatabase();
String controllo = "SELECT COUNT(_id) FROM tbf";
Cursor c = db.rawQuery(controllo, null);
while (c.moveToNext()){
int numero_id = c.getInt(0);
if(numero_id >=1){
// Bind Service
final boolean blnBind = getActivity().bindService(new Intent(
"com.android.vending.billing.InAppBillingService.BIND"),
mServiceConn, Context.BIND_AUTO_CREATE);
if (!blnBind) return;
if (mService == null) return;
Bundle ownedItems;
try {
ownedItems = mService.getPurchases(3, getActivity().getPackageName(), "inapp", null);
Intent intent = null;
intent = new Intent(getActivity(), Crea_e.class);
startActivity(intent);
} catch (RemoteException e) {
e.printStackTrace();
Toast.makeText(context, "getPurchases - fail!", Toast.LENGTH_SHORT).show();
Log.w(tag, "getPurchases() - fail!");
return;
}
int response = ownedItems.getInt("RESPONSE_CODE");
Toast.makeText(context, "getPurchases() - \"RESPONSE_CODE\" return " + String.valueOf(response), Toast.LENGTH_SHORT).show();
Log.i(tag, "getPurchases() - \"RESPONSE_CODE\" return " + String.valueOf(response));
if (response != 0) return;
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
Log.i(tag, "getPurchases() - \"INAPP_PURCHASE_ITEM_LIST\" return " + ownedSkus.toString());
Log.i(tag, "getPurchases() - \"INAPP_PURCHASE_DATA_LIST\" return " + purchaseDataList.toString());
Log.i(tag, "getPurchases() - \"INAPP_DATA_SIGNATURE\" return " + (signatureList != null ? signatureList.toString() : "null"));
Log.i(tag, "getPurchases() - \"INAPP_CONTINUATION_TOKEN\" return " + (continuationToken != null ? continuationToken : "null"));
}else {
Intent intent = null;
intent = new Intent(getActivity(), InAppBillingActivity.class);
startActivity(intent);
}
c.close();
db.close();
}
}
EDIT--------------------------------------------
private void Controlla_record_per_acquisto(){
SQLiteDatabase db = new DatabaseHelper(getActivity()).getReadableDatabase();
String controllo = "SELECT COUNT(_id) FROM FTB";
Cursor c = db.rawQuery(controllo, null);
while (c.moveToNext()){
int numero_id = c.getInt(0);
if(numero_id >=1){
Intent intent = null;
intent = new Intent(getActivity(), InAppBillingActivity.class);
startActivity(intent);
}else {
Intent intent = null;
intent = new Intent(getActivity(), Cure.class);
startActivity(intent);
}
c.close();
db.close();
}
}
I would suggest you to use the new Billing system, with the IabHelper class there you can do what you have described above both async/sync without the needs for "extra" code really.
http://developer.android.com/training/in-app-billing/preparing-iab-app.html