I was wondering how Android is doing that.
Example:
WAP Push indicates an incoming MMS.
Change APN to MMS.
Download MMS.
Restore connectivity to default APN.
So how is this change of APN done?
Why:
I want to use an other APN to connect to the internet instead of the default or MMS APN.
Following Activity solves your problem of changing default APN and than revert back to original.
package com.slk.apnapp;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
public class NewAPNActivity extends Activity {
/*
* Information of all APNs Details can be found in
* com.android.providers.telephony.TelephonyProvider
*/
public static final Uri APN_TABLE_URI = Uri
.parse("content://telephony/carriers");
/*
* Information of the preferred APN
*/
public static final Uri PREFERRED_APN_URI = Uri
.parse("content://telephony/carriers/preferapn");
private static final String TAG = "CHANGE_APN";
public static final String NEW_APN = "NewAPN";
private int getDafaultAPN() {
Cursor c = this.getContentResolver().query(PREFERRED_APN_URI,
new String[] { "_id", "name" }, null, null, null);
int id = -1;
if (c != null) {
try {
if (c.moveToFirst())
id = c.getInt(c.getColumnIndex("_id"));
} catch (SQLException e) {
Log.d(TAG, e.getMessage());
}
c.close();
}
return id;
}
/*
* Set an apn to be the default apn for web traffic Require an input of the
* apn id to be set
*/
public boolean setDefaultAPN(int id) {
boolean res = false;
ContentResolver resolver = this.getContentResolver();
ContentValues values = new ContentValues();
// See /etc/apns-conf.xml. The TelephonyProvider uses this file to
// provide
// content://telephony/carriers/preferapn URI mapping
values.put("apn_id", id);
try {
resolver.update(PREFERRED_APN_URI, values, null, null);
Cursor c = resolver.query(PREFERRED_APN_URI, new String[] { "name",
"apn" }, "_id=" + id, null, null);
if (c != null) {
res = true;
c.close();
}
} catch (SQLException e) {
Log.d(TAG, e.getMessage());
}
return res;
}
private int checkNewAPN() {
int id = -1;
Cursor c = this.getContentResolver().query(APN_TABLE_URI,
new String[] { "_id", "name" }, "name=?",
new String[] { NEW_APN }, null);
if (c == null) {
id = -1;
} else {
int record_cnt = c.getCount();
if (record_cnt == 0) {
id = -1;
} else if (c.moveToFirst()) {
if (c.getString(c.getColumnIndex("name")).equalsIgnoreCase(
NEW_APN)) {
id = c.getInt(c.getColumnIndex("_id"));
}
}
c.close();
}
return id;
}
public int addNewAPN() {
int id = -1;
ContentResolver resolver = this.getContentResolver();
ContentValues values = new ContentValues();
values.put("name", NEW_APN);
values.put("apn", NEW_APN);
/*
* The following three field values are for testing in Android emulator
* only The APN setting page UI will ONLY display APNs whose 'numeric'
* filed is TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC. On
* Android emulator, this value is 310260, where 310 is mcc, and 260
* mnc. With these field values, the newly added apn will appear in
* system UI.
*/
values.put("mcc", "310");
values.put("mnc", "260");
values.put("numeric", "310260");
Cursor c = null;
try {
Uri newRow = resolver.insert(APN_TABLE_URI, values);
if (newRow != null) {
c = resolver.query(newRow, null, null, null, null);
// Obtain the apn id
int idindex = c.getColumnIndex("_id");
c.moveToFirst();
id = c.getShort(idindex);
Log.d(TAG, "New ID: " + id + ": Inserting new APN succeeded!");
}
} catch (SQLException e) {
Log.d(TAG, e.getMessage());
}
if (c != null)
c.close();
return id;
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
int id = checkNewAPN();
int default_id = getDafaultAPN();
if (id == -1) {
id = addNewAPN();
}
if (setDefaultAPN(id)) {
Log.i(TAG, NEW_APN
+ " set new default APN successfully and Default id is "
+ id);
}
if (setDefaultAPN(default_id)) {
Log.i(TAG,
NEW_APN
+ " set previous default APN successfully and Default id is "
+ default_id);
}
}
}
Related
I have an application that runs under system account and one of the features is create custom APNs depending the client's configurations.
The code below works fine, but just create the APN and set it as default for simcard 1. O would like to set it depending on simcards if the software is running on Android 5 or above. I could not find any documentation about it. Anyone knows something else about APNs?
public static int createNewApn(Context context, APN apn, boolean setAsDefaultAPN) {
int apnid = -1;
try {
if (apn != null) {
Uri APN_URI = Uri.parse("content://telephony/carriers");
ContentResolver resolver = context.getContentResolver();
ContentValues values = prepareValues(apn);
Cursor c = null;
Uri newRow = resolver.insert(APN_URI, values);
if (newRow != null) {
c = resolver.query(newRow, null, null, null, null);
int tableIndex = c.getColumnIndex("_id");
c.moveToFirst();
apnid = c.getShort(tableIndex);
}
if (c != null) {
c.close();
}
if (apnid > -1 && setAsDefaultAPN) {
ContentValues v = new ContentValues(1);
v.put("apn_id", apnid);
context.getContentResolver().update(APN_PREFER_URI, v, null, null);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return apnid;
}
I use Google Calendar Provider for Android to add Events in my Google Calendar:
https://developer.android.com/guide/topics/providers/calendar-provider.html#overview
And this is the example to add Reminder for the Event:
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.MINUTES, 15);
values.put(CalendarContract.Reminders.EVENT_ID, reminderEventId);
values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
getContentResolver().insert(CalendarContract.Reminders.CONTENT_URI, values);
But in my Google Calendar app I can create Reminders without having EVENT_ID. Is it possible to create the same reminders with Google Calendar Provider for Android?
The same like this:
https://gsuiteupdates.googleblog.com/2016/04/launch-of-reminders-for-google-calendar.html
I have see that Google launch reminders for Google Calendar 2016 (This is a different Reminders from Event Reminders) and at the moment I can`t find in Android SDK (API 25) this kind of Google Calendar Reminders (and possibility to add programmatically appointment slots too).
A tricky approach I'm using is creating the remainders, instead of calendar, in the contacts, using Custom Reminder (and the ContactContract provider). So, you can use any label, and the reminder is shown in the specific date.
Cons:
- You have to have the "Birthday" calendar enable
- The remainder is date based (not time)
- They don't repeat the reminder (as the new calendar does)
package es.goodsal.mobile.provider.contact;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.provider.ContactsContract.CommonDataKinds.Event;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import es.goodsal.mobile.app.App;
import es.goodsal.mobile.model.ReminderType;
/**
* Created by jmalbarran on 16/9/17.
*/
public class Reminder implements Comparable<Reminder> {
private static final String TAG = Reminder.class.getSimpleName();
private static final SimpleDateFormat fullPeriodicDateFormat = new SimpleDateFormat("--MM-dd");
private static final SimpleDateFormat periodicDateFormat = new SimpleDateFormat("MM-dd");
private static final SimpleDateFormat nonPeriodicDateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final String DUE_DATE = Event.DATA4;
private static final String COMMENT = Event.DATA5;
private static final Uri CONTENT_URI = ContactsContract.Data.CONTENT_URI;
private static final String[] PROJECTION = new String[]{
Event._ID, //0
Event.CONTACT_ID, //1
Event.LOOKUP_KEY, //2
Event.START_DATE, //3
Event.TYPE, //4
Event.LABEL, //5 Label for custom event
Reminder.DUE_DATE, // 6
Reminder.COMMENT // 7 Use this field to save Comments
};
static {
periodicDateFormat.setCalendar(Calendar.getInstance()); // Set local time zone
nonPeriodicDateFormat.setCalendar(Calendar.getInstance()); // Set local time zone
}
private long id = -1;
private ConContact contact;
private Date reminderDate;
private Date dueDate;
private ReminderType type;
private String comment;
// region Constructor
public Reminder(ConContact contact, Date reminderDate,
Date dueDate, ReminderType type, String comment) {
this.contact = contact;
this.reminderDate = reminderDate;
this.dueDate = dueDate;
this.type = type;
this.comment = comment;
}
public Reminder(#NonNull String reminderUri) {
this(Uri.parse(reminderUri));
}
public Reminder(#NonNull Uri reminderUri) {
Cursor cursor;
cursor = App.getContentResolverInstance().query(reminderUri,
PROJECTION, null, null, null);
if (cursor == null) {
throw new IllegalArgumentException(reminderUri.toString() + " opportunity not found.");
} else {
cursor.moveToFirst();
setFromCursor(null, cursor);
}
}
private Reminder(#NonNull Cursor cursor) {
this(null, cursor);
}
private Reminder(#Nullable ConContact contact, #NonNull Cursor cursor) {
setFromCursor(contact, cursor);
}
private void setFromCursor(#Nullable ConContact contact, #NonNull Cursor cursor) {
int eventType;
String eventLabel;
Calendar calDueDate, calReminderDate;
Date now;
String strSplitDate[];
String strDueDate;
this.id = cursor.getLong(0);
if (contact != null) {
this.contact = contact;
} else {
this.contact = new ConContact(cursor.getLong(1), cursor.getString(2));
}
// Type
eventType = cursor.getInt(4); //Event.TYPE
eventLabel = cursor.getString(5); //Event.LABEL
switch (eventType) {
case ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY:
type = ReminderType.anniversary;
break;
case ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY:
type = ReminderType.birthday;
break;
case ContactsContract.CommonDataKinds.Event.TYPE_CUSTOM:
type = ReminderType.other;
eventLabel = cursor.getString(5);
for (ReminderType iType : ReminderType.values()) {
if (iType.getLabel().equals(eventLabel)) {
type = iType;
break;
}
}
break;
default:
type = ReminderType.other;
}
// Due / Reminder date
try {
now = new Date();
if (type.isPeriodic()) {
// Periodic Due date
calDueDate = Calendar.getInstance();
calDueDate.setTime(now);
strSplitDate = cursor.getString(6).split("-"); // DATA4
if (strSplitDate != null && strSplitDate.length == 3) {
calDueDate.set(Calendar.MONTH, Integer.parseInt(strSplitDate[1]));
calDueDate.set(Calendar.DAY_OF_MONTH, Integer.parseInt(strSplitDate[2]));
if (calDueDate.before(now)) { // Crossed end-of-year boundary
calDueDate.add(Calendar.YEAR, 1); // Next year
}
} else {
Log.e(TAG, "getReminders: Invalid date for periodic reminder due date " +
cursor.getString(6));
}
dueDate = calDueDate.getTime();
// Periodic Reminder date
calReminderDate = Calendar.getInstance();
calReminderDate.setTime(dueDate);
strSplitDate = cursor.getString(3).split("-"); // START_DATE
if (strSplitDate != null && strSplitDate.length == 3) {
calReminderDate.set(Calendar.MONTH, Integer.parseInt(strSplitDate[1]));
calReminderDate.set(Calendar.DAY_OF_MONTH, Integer.parseInt(strSplitDate[2]));
if (calReminderDate.after(dueDate)) { // Crossed end-of-year boundary
calDueDate.add(Calendar.YEAR, -11); // Previous year
}
} else {
Log.e(TAG, "getReminders: Invalid date for periodic reminder start date " +
cursor.getString(6));
}
reminderDate = calReminderDate.getTime();
} else {
// Non periodic date
reminderDate = nonPeriodicDateFormat.parse(cursor.getString(3)); // START_DATE
dueDate = nonPeriodicDateFormat.parse(cursor.getString(6)); // DATA4
dueDate = dueDate !=null ? dueDate : reminderDate;
}
} catch (Exception e) { // NullPointer and/or ParseFormat
dueDate = null;
reminderDate = null;
}
// Comment
comment = cursor.getString(7); // DATA5
}
// endregion Constructor
// region Getter/Setter
public Uri getUri() {
Uri uri;
uri = null;
if (id != -1) {
uri = ContentUris.withAppendedId(CONTENT_URI, id);
}
return uri;
}
public ConContact getContact() {
return contact;
}
public Date getReminderDate() {
return reminderDate;
}
public Date getDueDate() {
return dueDate;
}
public ReminderType getReminderType() {
return type;
}
public String getComment() {
return comment;
}
public boolean isPeriodic() {
return type.isPeriodic();
}
public void setContact(ConContact contact) {
this.contact = contact;
}
public void setReminderDate(Date reminderDate) {
this.reminderDate = reminderDate;
}
public void setDueDate(Date dueDate) {
this.dueDate = dueDate;
}
public void setType(ReminderType type) {
this.type = type;
}
public void setComment(String comment) {
this.comment = comment;
}
// endregion Getter/Setter
// region Commands
public boolean save() {
boolean ret;
ContentValues values;
Uri savedUri;
ret = false;
values = new ContentValues();
values.put(ContactsContract.CommonDataKinds.Event.MIMETYPE,
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
//values.put(ContactsContract.CommonDataKinds.Event.CONTACT_ID, contact.getContactId());
values.put(ContactsContract.CommonDataKinds.Event.RAW_CONTACT_ID, contact.getRawContactId());
if (type.isPeriodic()) {
values.put(ContactsContract.CommonDataKinds.Event.START_DATE,
fullPeriodicDateFormat.format(reminderDate));
values.put(ContactsContract.CommonDataKinds.Event.DATA4,
fullPeriodicDateFormat.format(dueDate));
} else {
values.put(ContactsContract.CommonDataKinds.Event.START_DATE,
nonPeriodicDateFormat.format(reminderDate));
values.put(ContactsContract.CommonDataKinds.Event.DATA4,
nonPeriodicDateFormat.format(dueDate));
}
values.put(ContactsContract.CommonDataKinds.Event.TYPE,
Integer.toString(type.getContactEventType()));
values.put(ContactsContract.CommonDataKinds.Event.LABEL, type.getLabel());
values.put(ContactsContract.CommonDataKinds.Event.DATA5, comment);
if (id == -1L) {
// Create new
savedUri = App.getContentResolverInstance().insert(ContactsContract.Data.CONTENT_URI, values);
id = ContentUris.parseId(savedUri);
ret = true;
Log.d(TAG, "save: Inserted uri=" + savedUri + " id=" + id);
} else {
// update existing id
// if (0<App.getContentResolverInstance().update(ContactsContract.Data.CONTENT_URI, values,
// ContactsContract.Data._ID + "='" + Long.toString(id) + "'", null)){
if (0 < App.getContentResolverInstance().update(
ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, id),
values,
null,
null)) {
ret = true;
Log.d(TAG, "save: Updated id=" + id);
} else {
Log.e(TAG, "save: Error updating id=" + id);
}
}
contact.resetReminders();
return ret;
}
public boolean delete() {
boolean ret = false;
if (id != -1) {
if (0 < App.getContentResolverInstance().delete(
ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, id),
null,
null)) {
Log.d(TAG, "delete: Deleted id=" + id);
ret = true;
} else {
Log.w(TAG, "delete: Not found id=" + id);
}
}
return ret;
}
// endregion Commands
#Override
public int compareTo(#NonNull Reminder o) {
if (reminderDate == null) {
return 1; // null always at end
} else {
if (o.reminderDate == null) {
return -1;
} else {
return reminderDate.compareTo(o.reminderDate);
}
}
}
/**
* Get reminders for all contact, in a specific date (including periodics)
*
* #param date exact to search for (reminder date NOT due date)
* #return List of reminders
*/
public static List<Reminder> getReminders(Date date) {
Cursor cursor;
ArrayList<Reminder> retList;
String where;
String[] selectionArgs;
Date dueDate;
String dateSelection;
String[] strSplitDate;
Calendar calDueDate;
retList = null;
Uri uri = ContactsContract.Data.CONTENT_URI;
String sortOrder = null;
// Execute one query per reminder type
for (ReminderType type : ReminderType.values()) {
dateSelection = type.isPeriodic() ?
"%" + periodicDateFormat.format(date) :
"%" + nonPeriodicDateFormat.format(date);
if (type.getContactEventType() == ContactsContract.CommonDataKinds.Event.TYPE_CUSTOM) {
// Check event label too
where = ContactsContract.CommonDataKinds.Event.MIMETYPE + "= ? AND " +
ContactsContract.CommonDataKinds.Event.START_DATE + " LIKE ? AND " +
ContactsContract.CommonDataKinds.Event.LABEL + "= ? AND " +
ContactsContract.CommonDataKinds.Event.TYPE + "=" + type.getContactEventType();
selectionArgs = new String[]{
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,
dateSelection,
type.getLabel()
};
} else {
// Non custom reminder. Don't check label
where = ContactsContract.CommonDataKinds.Event.MIMETYPE + "= ? AND " +
ContactsContract.CommonDataKinds.Event.START_DATE + " LIKE ? AND " +
ContactsContract.CommonDataKinds.Event.TYPE + "=" + type.getContactEventType();
selectionArgs = new String[]{
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,
dateSelection
};
} // where & selection per event type
cursor = App.getContentResolverInstance().query(uri, PROJECTION,
where, selectionArgs, sortOrder);
if (cursor != null) {
retList = new ArrayList<Reminder>();
while (cursor.moveToNext()) {
retList.add(new Reminder(cursor));
}
cursor.close();
} // if cursor
} // for per every type
return retList;
}
/**
* Get reminders for a specific contact, from a date forward
*
* #param contact Contact for search for
* #param date current or future date to search (including periodic)
* #return List of reminders for current or future search
*/
public static List<Reminder> getReminders(ConContact contact, Date date) {
Uri uri;
Cursor cursor;
ArrayList<Reminder> retList = null;
String where;
String[] selectionArgs;
String sortOrder;
int contactEventType;
String label;
Calendar calReminderDate, calDueDate;
String strReminderDate, strDueDate;
ReminderType type;
Date reminderDate;
Date dueDate;
String strDescription;
String[] strSplitDate;
uri = ContactsContract.Data.CONTENT_URI;
sortOrder = null;
// Check event label too
where = ContactsContract.CommonDataKinds.Event.MIMETYPE + " = ? AND " +
ContactsContract.CommonDataKinds.Event.CONTACT_ID + " = ? AND " +
"(" +
ContactsContract.CommonDataKinds.Event.START_DATE + " LIKE '--%' OR " +
ContactsContract.CommonDataKinds.Event.START_DATE + " >= ?" +
")";
selectionArgs = new String[]{
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,
Long.toString(contact.getContactId()),
nonPeriodicDateFormat.format(date)
};
sortOrder = ContactsContract.CommonDataKinds.Event.START_DATE;
cursor = App.getContentResolverInstance().query(uri, PROJECTION,
where, selectionArgs, sortOrder);
if (cursor != null) {
retList = new ArrayList<Reminder>();
while (cursor.moveToNext()) {
retList.add(new Reminder(contact, cursor));
}
Collections.sort(retList);
cursor.close();
} // if cursor
// for per every type
return retList;
}
} // end Reminder class
As stated in https://developer.android.com/guide/topics/providers/calendar-provider.html#overview
Reminders are specified in minutes before the event and have a method
that determines how the user will be alerted.
A reminder that doesn't belong to an event will not have a time of reference to go off.
I think for what you are trying to achieve () it would be best for you to look at Androids AlarmManager https://developer.android.com/reference/android/app/AlarmManager.html
Or see what other people are saying about similar things https://stackoverflow.com/a/16549111/6431430
I need to save the last visited webpage by user.
Evething works fine with my Galaxy S4 (5.0.1) with Chrome Browser.
However, on some phones I got nothing or very mixed results. From what I gathered, the biggest problem is with Browser URI itself. Some phones use Chrome as their main browser, some use something else.
I have three sources:
content://com.android.chrome.browser/bookmarks
content://com.sec.android.app.sbrowser/bookmarks
Browser.BOOKMARKS_URI
So right now I'm working on something like this:
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
h.removeCallbacks(this);
h.postDelayed(this, 500);
}
public void run() {
String[] proj = new String[] { Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL,Browser.BookmarkColumns.DATE };
String selection = Browser.BookmarkColumns.BOOKMARK + " = 0"; // 0 = history, 1 = bookmark
Cursor mCur = null;
try {
mCur = contentResolver.query(getURI(), proj, selection, null, null);
if(mCur != null && mCur.moveToLast()){
String title = "";
String url = "";
title = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.TITLE));
url = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.URL));
...
}
} catch (Exception e){
...
} finally {
if(mCur != null)
mCur.close();
}
}
private Uri getURI(){
Uri uri = Uri.parse("content://com.android.chrome.browser/bookmarks");
return uri;
}
Whet is the best way to provide correct URI?
onChange is triggered as content observer on browsers history.
So user can browse internet on Chrome and I still get history results from ASOP browser.
When I observe chrome directly, on some phones I get failed to find provider info, because there is no chrome installed.
What are other "popular" sources to search for browser history? I'd prefer to make this as bulletproof as possible.
try it: (run perfectly in android > 4.0 and 5 or 6.0 ); Anything, create a contentObserver array in FOREACH and add a list and record a different URI for each.
in service android (background):
HistoryObserver hObserver;
public void onCreate() {
hObserver = new HistoryObserver(new Handler(), this);
getApplicationContext().getContentResolver().registerContentObserver(Uri.parse("content://com.android.chrome.browser/history"), true, hObserver);
}
Class historicObserver:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.provider.Browser;
import android.util.Log;
public class HistoryObserver extends ContentObserver {
public final String TAG = "HistoryObserver";
Context context;
public HistoryObserver(Handler handler, Context c) {
super(handler);
Log.d(TAG, "Creating new HistoryObserver");
context = c;
}
public HistoryObserver(Context c) {
super(null);
Log.d(TAG, "Creating a new HistoryObserver without a Handler");
context = c;
}
#Override
public boolean deliverSelfNotifications() {
Log.d(TAG, "delivering self notifications");
return true;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.d(TAG, "onChange without uri: " + selfChange);
// onChange(selfChange, null);
}
#SuppressLint("NewApi")
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
Log.d(TAG, "onChange: " + selfChange + "\t " + uri.toString());
String[] proj = new String[] { Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL, Browser.BookmarkColumns.DATE };
String selection = Browser.BookmarkColumns.BOOKMARK + " = 0"; // 0 =
// history,
// 1 =
// bookmark
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Cursor mCursor = context.getContentResolver().query(Browser.BOOKMARKS_URI,
proj, selection, null, null);
// this.startManagingCursor(mCursor);
mCursor.moveToFirst();
int count = mCursor.getColumnCount();
String COUNT = String.valueOf(count);
Log.e("Browser sayac", COUNT);
String title = "";
String url = "";
String date = "";
if (mCursor.moveToFirst() && mCursor.getCount() > 0) {
while (mCursor.isAfterLast() == false) {
title = mCursor.getString(mCursor
.getColumnIndex(Browser.BookmarkColumns.TITLE));
url = mCursor.getString(mCursor
.getColumnIndex(Browser.BookmarkColumns.URL));
date = mCursor.getString(mCursor
.getColumnIndex(Browser.BookmarkColumns.DATE));
Long timestamp = Long.parseLong(date);
SimpleDateFormat dateFormat = new SimpleDateFormat(
"dd/MM/yyyy/HH:mm");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
String finaldate = dateFormat.format(calendar.getTime());
String smsDate = finaldate.toString();
// Log.e("DTE", date);
Log.e("URL", title);
Log.e("TARIH", smsDate);
mCursor.moveToNext();
}
}
}
}
I am successfully storing contacts in parse.com dashboard data browser by this code.
public void readContacts(){
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) ==1) {
System.out.println(name );
ParseObject testObject = new ParseObject("Contacts");
testObject.put("names", name);
// get the phone number
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String phone = pCur.getString(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println( phone);
testObject.put("phonenumber", phone);
}
pCur.close();
testObject.saveInBackground();
}
}
}
}
But there is no check for the duplicate contacts !
It stores all the contacts duplicate from sim / phone memory.
How can it be avoided ?
One possible method I think is to store distinct names(contact) in local database, & then retrieving that data to store it in parse.com
Is there exists a better way ?
Thanks in advance...
An easy approach could be to load the data to a MatrixCursor with no duplicate data. For example lets assume you have a cursor c1 will many contacts, but you need a cursor with no duplicate data. Here is what you could do:
MatrixCursor mc = new MatrixCursor(new String[] {
Phone._ID,
Phone.DISPLAY_NAME_PRIMARY,
Phone.NUMBER
});
String lastNumber = "";
while(c1.moveToNext()){
String id = c1.getString(c1.getColumnIndexOrThrow(Phone._ID));
String name = c1.getString(c1.getColumnIndexOrThrow(Phone.DISPLAY_NAME_PRIMARY)));
String number = c1.getString(c1.getColumnIndexOrThrow(Phone.NUMBER));
//Some condition to check previous data is not matched and only then add row
if(!lastNumber.contains(number)){
lastNumber = number;
mc.addRow(new String[]{id, name, number});
}
}
c1.close();
Make an instance of MatrixCursor with same columns, and then load if last number or contact name does not match that of the previous contact. The condition for checking is upto you. Query data in some order so that the duplicate contacts stay together first.
Once the MatrixCursor is loaded you can fetch data from it. You could also attach it to a view through a custom CursorLoader or CursorAdapter.
Please see the below method. You will get contacts list which does not have duplicate phone numbers.
public void readContacts() {
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
ArrayList<ParseObject> contacts = new ArrayList<ParseObject>();
ArrayList<String> list = new ArrayList<String>();
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) == 1) {
System.out.println(name);
ParseObject testObject = new ParseObject("Contacts");
testObject.put("names", name);
// get the phone number
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
while (pCur.moveToNext()) {
String phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println(phone);
testObject.put("phonenumber", phone);
if(!list.contains(phone)) {
contacts.add(testObject);
}
list.add(phone);
}
pCur.close();
testObject.saveInBackground();
}
}
}
}
Set is a collection in java that does not allow duplicates. You can put your data into a set with number as a key and name as value, to avoid duplicate numbers.
And later you can take them back from set and put into your testObject with name as key and number as value.
Here is the Solution that i worked out for you....
You can go through the logcat for information about how it works 100%
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
public class MainActivity extends Activity {
String ClsSimPhonename = null;
String ClsSimphoneNo = null;
public static ArrayList<String> phonecontact = new ArrayList<String>();
public static ArrayList<String> simcontact = new ArrayList<String>();
public static ArrayList<String> totalcontact = new ArrayList<String>();
public static ArrayList<String> repeatedcontact = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get phone contact...
getphonecontact();
// get sim contact...
getsimcard_contact();
System.out.println("phone??? " + phonecontact);
System.out.println("sim??? " + simcontact);
System.out.println("sim_size??? " + simcontact.size());
System.out.println("phone_size??? " + phonecontact.size());
System.out.println("totalcontact_size??? " + totalcontact.size());
// filter process beigins here....
nowFilterContact();
}
private void nowFilterContact() {
// TODO Auto-generated method stub
// determine which contact have more item....
if (simcontact.size() > phonecontact.size()) {
onemorefiltermethod(simcontact.size(), simcontact, phonecontact);
} else {
onemorefiltermethod(phonecontact.size(), phonecontact, simcontact);
}
}
private void onemorefiltermethod(int size, ArrayList<String> contacts,
ArrayList<String> contact2) {
// TODO Auto-generated method stub
// compare both contact and get repeated contacts....
for (int i = 0; i < size; i++) {
try {
if (contacts.contains(contact2.get(i))) {
// add repeated contacts to array....
repeatedcontact.add(contact2.get(i));
}
} catch (Exception e) {
}
}
System.out.println("repeatedcontact_size??? " + repeatedcontact.size());
// now delete repeated contact from total contact
now_deletedrepeated_contact_from_total();
}
private void now_deletedrepeated_contact_from_total() {
// TODO Auto-generated method stub
for (int i = 0; i < totalcontact.size(); i++) {
try {
if (totalcontact.contains(repeatedcontact.get(i))) {
totalcontact.remove(repeatedcontact.get(i));
}
} catch (Exception e) {
}
}
System.out.println("Final contact size" + totalcontact.size());
System.out.println("Final contact " + totalcontact);
}
private void getsimcard_contact() {
// TODO Auto-generated method stub
try {
Uri simUri = Uri.parse("content://icc/adn");
Cursor cursorSim = this.getContentResolver().query(simUri, null,
null, null, null);
while (cursorSim.moveToNext()) {
ClsSimPhonename = cursorSim.getString(cursorSim
.getColumnIndex("name"));
ClsSimphoneNo = cursorSim.getString(cursorSim
.getColumnIndex("number"));
ClsSimphoneNo.replaceAll("\\D", "");
ClsSimphoneNo.replaceAll("&", "");
ClsSimPhonename = ClsSimPhonename.replace("|", "");
/*
* add contact from phone to array phone array and total array
*/
phonecontact.add(ClsSimphoneNo);
totalcontact.add(ClsSimphoneNo);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void getphonecontact() {
// TODO Auto-generated method stub
try {
String[] PROJECTION = new String[] { Contacts._ID,
Contacts.DISPLAY_NAME, Phone.NUMBER };
Cursor c = managedQuery(Phone.CONTENT_URI, PROJECTION, null, null,
null);
if (c.moveToFirst()) {
String ClsPhonename = null;
String ClsphoneNo = null;
do {
ClsPhonename = c.getString(c
.getColumnIndex(Contacts.DISPLAY_NAME));
ClsphoneNo = c.getString(c.getColumnIndex(Phone.NUMBER));
/*
* add contact from sim to array sim array and total array
*/
simcontact.add(ClsphoneNo);
totalcontact.add(ClsphoneNo);
ClsphoneNo.replaceAll("\\D", "");
ClsPhonename = ClsPhonename.replaceAll("&", "");
ClsPhonename.replace("|", "");
String ClsPhoneName = ClsPhonename.replace("|", "");
} while (c.moveToNext());
}
} catch (Exception e) {
}
}
}
Permission
<uses-permission android:name="android.permission.READ_CONTACTS"/>
Your output is on now_deletedrepeated_contact_from_total() method.
Check totalcontact array value for Final output
I'm simply getting the all contact list to an object (PhoneBookContact):
private static final Uri PURI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private static final String PID = ContactsContract.CommonDataKinds.Phone._ID;
private static final String PNAME = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME;
private static final String PNUM = ContactsContract.CommonDataKinds.Phone.NUMBER;
String[] projection = new String[]{PID, PNAME, PNUM};
String sortOrder = PNAME + " COLLATE LOCALIZED ASC";
Cursor people = mContext.getContentResolver().query(PURI, projection, null, null, sortOrder);
int indexid = people.getColumnIndex(PID);
int indexName = people.getColumnIndex(PNAME);
int indexNumber = people.getColumnIndex(PNUM);
people.moveToFirst();
do {
PhoneBookContact phoneBookContact = new PhoneBookContact();
phoneBookContact.setmCursorId(people.getLong(indexid));
phoneBookContact.setmDisplayName(people.getString(indexName));
phoneBookContact.setmPhoneNumber(UriFactory.formatNumberToInternational(people.getString(indexNumber)));
phoneList.put(phoneBookContact.getmPhoneNumber(), phoneBookContact);
} while (people.moveToNext());
people.close();
To fetch the photo of the user from Android Contacts, I'am using this method:
public static Uri loadContactPhotoUri(ContentResolver contentResolver, long id) {
try {
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
return person;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
Finally, this code gives this URI for a specific user:
content://com.android.contacts/contacts/5907
Since I'm calling this URI with ContactsContract.CommonDataKinds.Phone._ID id, I can't get the photo of the user successfully. In fact, it should be the id of ContactsContract.Contacts._ID. How can I query the photo of the user and fix this problem?
Instead of ContactsContract.CommonDataKinds.Phone._ID, you must use ContactsContract.CommonDataKinds.Phone.CONTACT_ID to save the cursorID of Contacts table. It solved my problem.
This file have funtion get contact photo
https://github.com/heinrisch/Contact-Picture-Sync/blob/master/src/heinrisch/contact/picture/sync/ContactHandler.java
package heinrisch.contact.picture.sync;
import java.io.InputStream;
import java.util.ArrayList;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDiskIOException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Data;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;
public class ContactHandler {
public static ArrayList<String> getNumbers(String ID, Context context){
ArrayList<String> numbers = new ArrayList<String>();
ContentResolver cr = context.getContentResolver();
Cursor phones = cr.query(Phone.CONTENT_URI, null,Phone.CONTACT_ID + " = " + ID, null, null);
while (phones.moveToNext()) {
numbers.add(phones.getString(phones.getColumnIndex(Phone.NUMBER)));
}
phones.close();
return numbers;
}
public static void matchContactsToFriends(ArrayList<Friend> friends, Context context) {
Cursor people = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if(people == null){
Log.e("ContactHandler", "Could not find contacts...?");
return;
}
while(people.moveToNext()) {
String ID = null,name = null;
int columnIndex = people.getColumnIndex(ContactsContract.Contacts._ID);
if(columnIndex != -1) ID = people.getString(columnIndex);
columnIndex = people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
if(columnIndex != -1) name = people.getString(columnIndex);
//ArrayList<String> numbers = getNumbers(ID,context); //"can't" get this from facebook
if(name == null) continue;
for(Friend f : friends){
if(f.isMatchedWithContact()) continue;
if(f.getName().equals(name)){
f.setContactID(ID);
Bitmap contactPhoto = getPhoto(context, ID);
if(contactPhoto != null) f.setContactPicture(contactPhoto);
break;
}
}
}
people.close();
}
public static void setContactPicture(Friend f, Context context){
f.setContactPicture(getPhoto(context, f.getContactID()));
}
public static int getNumberOfContacts(Context context) {
Cursor people = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
int numberOfContacts = people.getCount();
people.close();
return numberOfContacts;
}
public static Uri getPicture(Context context, String ID){
ContentResolver cr = context.getContentResolver();
Uri rawContactUri = null;
Cursor rawContactCursor = cr.query(RawContacts.CONTENT_URI, new String[] {RawContacts._ID}, RawContacts.CONTACT_ID + " = " + ID, null, null);
if(!rawContactCursor.isAfterLast()) {
rawContactCursor.moveToFirst();
rawContactUri = RawContacts.CONTENT_URI.buildUpon().appendPath(""+rawContactCursor.getLong(0)).build();
}
rawContactCursor.close();
return rawContactUri;
}
public static void setContactPicture(Context context, String ID, Bitmap picture){
ContentResolver cr = context.getContentResolver();
Uri rawContactUri = getPicture(context, ID);
if(rawContactUri == null){
Log.e("rawContactUri", "is null");
return;
}
ContentValues values = new ContentValues();
int photoRow = -1;
String where = ContactsContract.Data.RAW_CONTACT_ID + " == " +
ContentUris.parseId(rawContactUri) + " AND " + Data.MIMETYPE + "=='" +
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, null, where, null, null);
int idIdx = cursor.getColumnIndexOrThrow(ContactsContract.Data._ID);
if(cursor.moveToFirst()){
photoRow = cursor.getInt(idIdx);
}
cursor.close();
values.put(ContactsContract.Data.RAW_CONTACT_ID,
ContentUris.parseId(rawContactUri));
values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, Tools.bitmapToByteArray(picture));
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
try{
if(photoRow >= 0){
cr.update(
ContactsContract.Data.CONTENT_URI,
values,
ContactsContract.Data._ID + " = " + photoRow, null);
} else {
cr.insert(
ContactsContract.Data.CONTENT_URI,
values);
}
}catch(SQLiteDiskIOException dIOe){
//TODO: should show this to the user..
dIOe.printStackTrace();
}
}
public static Bitmap getPhoto(Context context, String contactId) {
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
if (input == null) {
return null;
}
return BitmapFactory.decodeStream(input);
}
}