Add the contents of one Cursor to another Cursor - android

I want to join two cursors so that the contents of the second Cursor shall also appear in first Cursor after joining.
Precisely here is my code,
public final Uri AllImage_URI_Int = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
public final Uri AllAudio_URI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
cContentList = managedQuery(AllImage_URI_Int, null, null, null, MediaStore.Images.ImageColumns.TITLE);
cList_Int = managedQuery(AllImage_URI, null, null, null, MediaStore.Images.ImageColumns.TITLE);
Should i use the CursorJoiner in this case?
I want to pass this Cursor to SimpleListAdapter? How can i join those two cursors?

Maybe you can use a MergeCursor wrapper to merge your two Cursors into a new one, and pass it to your Adapter.

well, i solved it myself and working, extendeb by AbstractCursor, heres the code,
private final int ROWCACHESIZE = 64;
private int mRowNumCache[] = new int[ROWCACHESIZE];
private int mCursorCache[] = new int[ROWCACHESIZE];
private int mCurRowNumCache[][];
private int mLastCacheHit = -1;
public SortCursor(Cursor[] cursors, String sortcolumn)
{
mCursors = cursors;
int length = mCursors.length;
mSortColumns = new int[length];
for (int i = 0 ; i < length ; i++) {
if (mCursors[i] == null) continue;
mCursors[i].moveToFirst();
// We don't catch the exception
mSortColumns[i] = mCursors[i].getColumnIndexOrThrow(sortcolumn);
}
mCursor = null;
String smallest = "";
for (int j = 0 ; j < length; j++) {
if (mCursors[j] == null || mCursors[j].isAfterLast())
continue;
String current = mCursors[j].getString(mSortColumns[j]);
if (mCursor == null || current.compareToIgnoreCase(smallest) < 0) {
smallest = current;
mCursor = mCursors[j];
}
}
for (int i = mRowNumCache.length - 1; i >= 0; i--) {
mRowNumCache[i] = -2;
}
mCurRowNumCache = new int[ROWCACHESIZE][length];
}

Related

Cursor only returning one value / last value

I am really stuck as I have a cursor that retrieves values from the database but the cursor only returns the last value. I need the cursor to retrieve all values so I can display them all later on. Is there any way as I can return all the data stored through the cursor?
An Example as to whats happening. Eg Click on Button 1 and stores 1 perfectly but once I click on Button 2 and add 1. Button 1 data is not return or retrieved.
Any help would be greatly appreciated.
Execute
The first Cursor is goes through to check all the stored items.
public void exectute() {
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Cursor c = TrackerDb.getStoredItems(getApplicationContext());
if (c != null) {
if (c.moveToFirst()) {
WorkoutDetails details = null;
//if (details != null) mWorkoutDetailsList.add(details);
do {
//if (details != null) mWorkoutDetailsList.add(details);
WorkoutDetails temp = getWorkoutFromCursor(c);
//if (details != null) mWorkoutDetailsList.add(details);
if (details == null) {
details = temp;
continue;
}
//if (details != null) mWorkoutDetailsList.add(details);
if (isSameDay(details.getWorkoutDate(), temp.getWorkoutDate())) {
//if (details != null) mWorkoutDetailsList.add(details);
if (DBG) Log.d(LOG_TAG, "isSameDay().. true");
//details.add(temp);
} else {
mWorkoutDetailsList.add(details);
details = temp;
}
// if (details != null) mWorkoutDetailsList.add(details);
} while (c.moveToNext());
if (details != null) mWorkoutDetailsList.add(details);
if (DBG)
Log.d(LOG_TAG, "AsyncTask: list size " + mWorkoutDetailsList.size());
runOnUiThread(new Runnable() {
#Override
public void run() {
mWorkoutsAdapter.updateList(mWorkoutDetailsList);
}
});
}
c.close();
}
}
});
}
Get Stored Items Code
This is the code which the excute class calls and where the cursor only returns one value.
public static Cursor getStoredItems(Context context) {
DBHelper dbHelper = new DBHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();
String[] projection = {ID, TIME, TYPE, DURATION, DATE, POINT};
String orderBy = TIME + " DESC";
Cursor cursor = db.query(TABLE_NAME, projection, null, null, null, null, orderBy);
return cursor;
}
Array
This is the array code where i want the cursor to store its values based on type.
private WorkoutDetails getWorkoutFromCursor(Cursor c) {
long time = c.getLong(c.getColumnIndex(TrackerDb.TIME));
int type = c.getInt(c.getColumnIndex(TrackerDb.TYPE));
int duration = c.getInt(c.getColumnIndex(TrackerDb.DURATION));
int point = c.getInt(c.getColumnIndex(TrackerDb.POINT));
int totalMoney = MoneyActivity.Money.values().length;
int[] points = new int[totalMoney];
int totalActivities = MeditationTrackerActivity.ACTIVITIES.values().length;
int[] durations = new int[totalActivities];
if (type < totalActivities) {
durations[type] = duration;
}
if( type == 0) {
for (int i = 0; i < totalMoney; i++) {
points[type] = point;
}
}
else if ( type == 1) {
for ( int ii = 0; ii < totalMoney; ii++) {
points[type] = point;
}
}
else if ( type == 2) {
for ( int iii = 0; iii < totalMoney; iii++) {
points[type] = point;
}
}
return new WorkoutDetails(time, durations, points);
}
Get Workout From Cursor Code
private static WorkoutDetails getWorkoutFromCursor(Cursor c) {
long time = c.getLong(c.getColumnIndex(TrackerDb.TIME));
int type = c.getInt(c.getColumnIndex(TrackerDb.TYPE));
int duration = c.getInt(c.getColumnIndex(TrackerDb.DURATION));
String date = c.getString(c.getColumnIndex(TrackerDb.DATE));
int point = c.getInt(c.getColumnIndex(TrackerDb.POINT));
int[] durations = new int[MeditationTrackerActivity.ACTIVITIES.values().length];
durations[type] = duration;
int[] points = new int[MoneyActivity.Money.values().length];
points[type] = point;
return new WorkoutDetails(time, durations, date, points);
}

Contact Joining (Android M)

i try to join two Contacts, a default Contact from the Default Address-Store, and a Contact of my own Provider.
I have the following code-snippet of the com.android.Contact app:
private interface JoinContactQuery {
String[] PROJECTION = {
RawContacts._ID,
RawContacts.CONTACT_ID,
RawContacts.NAME_VERIFIED,
RawContacts.DISPLAY_NAME_SOURCE,
};
String SELECTION = RawContacts.CONTACT_ID + "=? OR " + RawContacts.CONTACT_ID + "=?";
int _ID = 0;
int CONTACT_ID = 1;
int NAME_VERIFIED = 2;
int DISPLAY_NAME_SOURCE = 3;
}
Cursor c = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
JoinContactQuery.PROJECTION,
JoinContactQuery.SELECTION,
new String[]{String.valueOf(contactId1), String.valueOf(contactId2)}, null);
if (c == null) {
Log.e(TAG, "Unable to open Contacts DB cursor");
return;
}
long rawContactIds[];
long verifiedNameRawContactId = -1;
try {
if (c.getCount() == 0) {
return;
}
int maxDisplayNameSource = -1;
rawContactIds = new long[c.getCount()];
for (int i = 0; i < rawContactIds.length; i++) {
c.moveToPosition(i);
long rawContactId = c.getLong(JoinContactQuery._ID);
rawContactIds[i] = rawContactId;
int nameSource = c.getInt(JoinContactQuery.DISPLAY_NAME_SOURCE);
if (nameSource > maxDisplayNameSource) {
maxDisplayNameSource = nameSource;
}
}
// Find an appropriate display name for the joined contact:
// if should have a higher DisplayNameSource or be the name
// of the original contact that we are joining with another.
if (writable) {
for (int i = 0; i < rawContactIds.length; i++) {
c.moveToPosition(i);
if (c.getLong(JoinContactQuery.CONTACT_ID) == contactId1) {
int nameSource = c.getInt(JoinContactQuery.DISPLAY_NAME_SOURCE);
if (nameSource == maxDisplayNameSource
&& (verifiedNameRawContactId == -1
|| c.getInt(JoinContactQuery.NAME_VERIFIED) != 0)) {
verifiedNameRawContactId = c.getLong(JoinContactQuery._ID);
}
}
}
}
} finally {
c.close();
}
// For each pair of raw contacts, insert an aggregation exception
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
for (int i = 0; i < rawContactIds.length; i++) {
for (int j = 0; j < rawContactIds.length; j++) {
if (i != j) {
buildJoinContactDiff(operations, rawContactIds[i], rawContactIds[j]);
}
}
}
// Mark the original contact as "name verified" to make sure that the contact
// display name does not change as a result of the join
if (verifiedNameRawContactId != -1) {
Builder builder = ContentProviderOperation.newUpdate(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, verifiedNameRawContactId));
builder.withValue("name_verified", 1);
operations.add(builder.build());
}
My Problem: The "name_verified" Field is removed on Android M (Preview 2). Whats the "correct" way to join two Contacts (and do not change the Name of the Contact)?
* EDIT / Solution *
Remove name_verified and set "IS_SUPER_PRIMARY" to content uri
//mark as SUPER PRIMARY
if (verifiedNameRawContactId != -1) {
operations.add(
ContentProviderOperation.newUpdate(ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, verifiedNameRawContactId))
.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
.build());
}
The question is not quite clear to me but i think your are trying to join two contacts and one name is taking precedence over another but not the way you want it.
The correct way to join contacts is to add a row in this table and keep the type as TYPE_KEEP_TOGETHER. AggregationsExceptions table
If you want to keep the name of the first raw_contact mark the name record of the contact in Data table (StructuredName) as IS_SUPER_PRIMARY
IS_SUPER_PRIMARY

Access location data from Image in library

I have a method that, given a Uri, should retrieve the location data from that photo. However, all I am getting is zeros from the cursor.GetDouble(latitudeColumnIndex); method
What am I missing?
private void GetImageLocation(Uri uri)
{
string[] projection =
{
MediaStore.Images.Media.InterfaceConsts.Latitude,
MediaStore.Images.Media.InterfaceConsts.Longitude,
};
using (ICursor cursor = ContentResolver.Query(uri, projection, null, null, null))
{
if (cursor.MoveToFirst())
{
int latitudeColumnIndex = cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Latitude);
int longitudeColumnIndex = cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Longitude);
if (latitudeColumnIndex == -1 || longitudeColumnIndex == -1)
{
_newPhoto.Latitude = 0;
_newPhoto.Longitude = 0;
}
_newPhoto.Latitude = cursor.GetDouble(latitudeColumnIndex);
_newPhoto.Longitude = cursor.GetDouble(longitudeColumnIndex);
}
else
{
_newPhoto.Latitude = 0;
_newPhoto.Longitude = 0;
}
cursor.Close();
}
}
You should try using ExifInterface.GetLatLong.
It receives a float array (where the latitude and longitude will be stored) and returns a bool indicating whether the operation succeeded or not. Its usage is something like this:
var exif = new ExifInterface(uri.Path);
var latLong = new float[2];
float lat, long;
//Check if Latitude and Longitude can be retrieved
if(exif.GetLatLong(latLong))
{
lat = latLong[0];
long = latLong[1];
}
else
{
//Fallback
lat = 0;
long = 0;
}

Android for loop List

I have a list that is populated with data taken from database.
The data of the list are passed to the view to display them. For each id taken from the database, I want to add a day to the calendar, then, I added the id what I need in an array, in order to have them sorted.
The problem is the loop in the list, instead of iterating based on the number of id in the array, the cycle continues without stopping ... I hope I explained, this is all the code
private Integer[] id_nome_op;
public void checkOperatori() {
SQLiteDatabase db = new DatabaseHelper(getActivity()).getReadableDatabase();
String OPERATORI = "SELECT _id, ...... ORDER BY _id ASC";
Cursor cur = db.rawQuery(OPERATORI, null);
int count = cur.getCount();
id_nome_op = new Integer[count];
nome_op = new String[count];
cognome_op = new String[count];
for (int i = 0; i < count; i++) {
cur.moveToNext();
id_nome_op[i] = cur.getInt(0);
nome_op[i] = cur.getString(1);
cognome_op[i] = cur.getString(2);
mWeekView.setData(nome_op, cognome_op);
}
cur.close();
db.close();
}
#Override
public List<WeekViewEvent>onMonthChange(int newYear, int newMonth) {
SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd");
final String strDate = simpleFormat.format(calendarioFooter.getTime());
List<WeekViewEvent> events = new ArrayList<WeekViewEvent>();
SQLiteDatabase db = new DatabaseHelper(getActivity()).getReadableDatabase();
String tabella_op = "SELECT m._id, m.id_operatore, ...........";
Cursor cur = db.rawQuery(tabella_op, null);
while (cur.moveToNext()) {
startTime = (Calendar) calendarioFooter.clone();
id_appuntamento = cur.getString(0);
id_operator = cur.getInt(1);
dat = cur.getString(2);
ora_iniz = cur.getString(3);
ora_fin = cur.getString(4);
id_servizio = cur.getString(5);
id_client = cur.getString(6);
nome_cliente = cur.getString(7);
cognome_cliente = cur.getString(8);
nome_operatore = cur.getString(9);
colore_serv = cur.getInt(10);
tipo_serv = cur.getString(11);
int giorno_ok = Integer.parseInt(dat.substring(8, 10));
int ora_inizio = Integer.parseInt(ora_iniz.substring(0, 2));
int minuto_inizio = Integer.parseInt(ora_iniz.substring(3, 5));
int ora_fine = Integer.parseInt(ora_fin.substring(0, 2));
int minuto_fine = Integer.parseInt(ora_fin.substring(3, 5));
int size = id_nome_op.length;//array id
for(int i = 1; i< size; i++){
if (i == 1) {
startTime.set(Calendar.DAY_OF_MONTH, giorno_ok);
} else if (i == 2) {
startTime.set(Calendar.DAY_OF_MONTH, giorno_ok);
startTime.add(Calendar.DATE, 1);
} else if (i == 3) {
startTime.set(Calendar.DAY_OF_MONTH, giorno_ok);
startTime.add(Calendar.DATE, 2);
}
startTime.set(Calendar.HOUR_OF_DAY, ora_inizio);
startTime.set(Calendar.MINUTE, minuto_inizio);
startTime.set(Calendar.MONTH, newMonth - 1);
startTime.set(Calendar.YEAR, newYear);
Calendar endTime = (Calendar) startTime.clone();
endTime.set(Calendar.HOUR_OF_DAY, ora_fine);
endTime.set(Calendar.MINUTE, minuto_fine);
WeekViewEvent event = new WeekViewEvent(id_appuntamento, getEventTitle(startTime), startTime, endTime);
event.setColor(colore_serv);
events.add(event);
}
}
cur.close();
db.close();
return events;
}

regular-expressions android

i have string like these for example
309\306\308\337_338
309\306\337_338
310
311\315_316\336_337
311\315_316\336_337
311\335_336
these strings means list of page number , for example string "309\306\308\337_339" means
pages 309,306,308,337,338,339
i want to pass one of these string to function which return it as string like this
309,306,308,337,338,339
this function do that but in c# , i want to impalement in android
private static string Get_PageNumbers(string str)
{
ArrayList arrAll = new ArrayList();
MatchCollection match;
string[] excar;
string strid, firstNumber, lastlNumber;
int fn, ln;
ArrayList arrID = new ArrayList();
//***In Case The Range Number Between "_"
if (str.Contains("_"))
{
// match_reg = new Regex("(w?[\\d]+)*(_[\\d]+)");
Regex matchReg = new Regex("(w?[\\69]+_[\\d]+)*(q?[\\d]+//)*(a?[\\d]+_[\\d]+)*(y?[\\d]+)*");
match = matchReg.Matches(str);
int count = match.Count;
excar = new string[0];
for (int i = 0; i < count; i++)
{
Array.Resize(ref excar, count);
excar[i] = match[i].Groups[0].Value;
if (excar[i] != string.Empty)
arrID.Add(excar[i]);
}
//******IF Array Contains Range Of Number Like"102_110"
if (str.Contains("_"))
{
for (int i = 0; i < arrID.Count; i++)
{
strid = arrID[i].ToString();
if (arrID[i].ToString().Contains("_"))
{
int idy = strid.LastIndexOf("_");
firstNumber = strid.Substring(0, idy);
if (idy != -1)
{
lastlNumber = strid.Substring(idy + 1);
fn = int.Parse(firstNumber);
arrAll.Add(fn);
ln = int.Parse(lastlNumber);
for (int c = fn; c < ln; c++)
{
fn++;
arrAll.Add(fn);
}
}
}
else
{
arrAll.Add(arrID[i].ToString());
}
}
//******If Array Contain More Than One Number
if (arrAll.Count > 0)
{
str = "";
for (int i = 0; i < arrAll.Count; i++)
{
if (str != string.Empty)
str = str + "," + arrAll[i];
else
str = arrAll[i].ToString();
}
}
}
}
//***If string Contains between "/" only without "_"
else if (str.Contains("/") && !str.Contains("_"))
{
str = str.Replace("/", ",");
}
else if (str.Contains("\\"))
{
str = str.Replace("\\", ",");
}
return str;
}
I think this is easier to do with split function:
public static String Get_PageNumbers(String str) {// Assume str = "309\\306\\308\\337_338"
String result = "";
String[] pages = str.split("\\\\"); // now we have pages = {"309","306","308","337_338"}
for (int i = 0; i < pages.length; i++) {
String page = pages[i];
int index = page.indexOf('_');
if (index != -1) { // special case i.e. "337_338", index = 3
int start = Integer.parseInt(page.substring(0, index)); // start = 337
int end = Integer.parseInt(page.substring(index + 1)); // end = 338
for (int j = start; j <= end; j++) {
result += String.valueOf(j);
if (j != end) { // don't add ',' after last one
result += ",";
}
}
} else { // regular case i.e. "309","306","308"
result += page;
}
if (i != (pages.length-1)) { // don't add ',' after last one
result += ",";
}
}
return result; // result = "309,306,308,337,338"
}
For example this function when called as follows:
String result1 = Get_PageNumbers("309\\306\\308\\337_338");
String result2 = Get_PageNumbers("311\\315_316\\336_337");
String result3 = Get_PageNumbers("310");
Returns:
309,306,308,337,338
311,315,316,336,337
310
if i can suggest different implementation....
first, split string with "\" str.split("\\");, here you receive an array string with single number or a pattern like "num_num"
for all string founded, if string NOT contains "" char, put string in another array (othArr named), than, you split again with "" str.split("_");, now you have a 2 position array
convert that 2 strings in integer
now create a loot to min val form max val or two strings converted (and put it into othArr)
tranform othArr in a string separated with ","

Categories

Resources