Scoped Storage android 10.0 - java

Crash is here......
android.database.sqlite.SQLiteException: near "GROUP": syntax error (Sqlite code 1 SQLITE_ERROR): , while compiling: SELECT _id, bucket_display_name, bucket_id, _id, orientation FROM images WHERE ((is_pending=0) AND (is_trashed=0) AND (volume_name IN ( 'external_primary' ))) AND ((1) GROUP BY 1,(2)) ORDER BY date_modified DESC, (OS error - 2:No such file or directory)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:184)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
at android.content.ContentResolver.query(ContentResolver.java:955)
at android.content.ContentResolver.query(ContentResolver.java:891)
at android.content.ContentResolver.query(ContentResolver.java:840)
Below is method to show all folders or album of images.
private boolean logGalleryFolders() {
this.albumList = new ArrayList<>();
List<Integer> bucketIdList = new ArrayList<>();
Cursor cur = this.context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, new String[]{"_id", "bucket_display_name", "bucket_id", "_id", "orientation"}, "1) GROUP BY 1,(2", null, "date_modified DESC");
List<GridViewItem> items;
int i;
if (cur == null || !cur.moveToFirst()) {
items = new ArrayList<>();
for (i = 0; i < this.albumList.size(); i++) {
items.add(new GridViewItem(this.activity, this.albumList.get(i).name, BuildConfig.FLAVOR + this.albumList.get(i).imageIdList.size(), true, this.albumList.get(i).imageIdForThumb, this.albumList.get(i).orientationList.get(0).intValue()));
}
this.albumList.add(new Album());
this.albumList.get(this.albumList.size() - 1).gridItems = items;
for (i = 0; i < this.albumList.size() - 1; i++) {
this.albumList.get(i).gridItems = createGridItemsOnClick(i);
}
if (cur != null) {
cur.close();
}
return true;
}
int bucketColumn = cur.getColumnIndex("bucket_display_name");
int bucketId = cur.getColumnIndex("bucket_id");
int imageId = cur.getColumnIndex("_id");
int orientationColumnIndex = cur.getColumnIndex("orientation");
do {
Album album = new Album();
int id = cur.getInt(bucketId);
album.ID = id;
if (bucketIdList.contains(id)) {
Album albumFromList = this.albumList.get(bucketIdList.indexOf(album.ID));
albumFromList.imageIdList.add(cur.getLong(imageId));
albumFromList.orientationList.add(cur.getInt(orientationColumnIndex));
} else {
String bucket = cur.getString(bucketColumn);
bucketIdList.add(id);
album.name = bucket;
album.imageIdForThumb = cur.getLong(imageId);
album.imageIdList.add(album.imageIdForThumb);
this.albumList.add(album);
album.orientationList.add(cur.getInt(orientationColumnIndex));
}
} while (cur.moveToNext());
items = new ArrayList<>();
for (i = 0; i < this.albumList.size(); i++) {
items.add(new GridViewItem(this.activity, this.albumList.get(i).name, BuildConfig.FLAVOR + this.albumList.get(i).imageIdList.size(), true, this.albumList.get(i).imageIdForThumb, this.albumList.get(i).orientationList.get(0).intValue()));
}
this.albumList.add(new Album());
this.albumList.get(this.albumList.size() - 1).gridItems = items;
for (i = 0; i < this.albumList.size() - 1; i++) {
this.albumList.get(i).gridItems = createGridItemsOnClick(i);
}
cur.close();
return true;
}
Below is crash line......
Cursor cur = this.context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, new String[]{"_id", "bucket_display_name", "bucket_id", "_id", "orientation"}, "1) GROUP BY 1,(2", null, "date_modified DESC");

Just change the query like below:
From
Cursor cur = this.context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, new String[]{"_id", "bucket_display_name", "bucket_id", "_id", "orientation"}, "1) GROUP BY 1,(2", null, "date_modified DESC");
To
Cursor cur = this.context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, new String[]{"_id", "bucket_display_name", "bucket_id", "_id", "orientation"}, null, null, "date_modified DESC");

Your GROUP BY comes inside the And makes the issue. Please change your query as below:
SELECT
_id,
bucket_display_name,
bucket_id,
_id,
orientation
FROM
images
WHERE
(
(is_pending = 0)
AND (is_trashed = 0)
AND (volume_name IN ('external_primary'))
)
AND ((1))
GROUP BY
1,(2)
ORDER BY
date_modified DESC

Related

Find Duplicate Image from External Storage

I want to find Duplicate Images from External Storage.
In my current solution I successfully find Duplicates.
But when the data is large, the processing time long.
My current design first gets all images, then loops to find duplicates.
Here is my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AllImages_1 = getImagesList(); // AllImages_1 is a array list
}
private ArrayList<File> getImagesList() {
Uri uri;
Cursor cursor;
int column_index_data;
ArrayList<File> listOfAllImages = new ArrayList<>();
String absolutePathOfImage = null;
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
cursor = MainActivity.this.getContentResolver().query(uri, projection, null,
null, null);
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
listOfAllImages.add(new File(absolutePathOfImage));
}
return listOfAllImages;
}
below code is find Dulpicate
public void CheckedDuplicateImage() {
int Group = 1;
arrayList.clear();
ArrayList<String> grpind = new ArrayList<>();
for (int i = 0; i < AllImages_1.size(); i++) {
ArrayList<VideoDataClass> group = new ArrayList<>();
duplicate = false;
boolean duplicate_I = false;
if (grpind.contains(String.valueOf(i))) {
continue;
}
for (int j = 0; j < AllImages_1.size(); j++) {
if (i != j && (AllImages_1.get(i).length() == AllImages_1.get(j).length() ||
AllImages_1.get(i).getName() == AllImages_1.get(j).getName())) {
if (!duplicate_I) {
group.add(OriginalFile(AllImages_1.get(i)));
duplicate_I = true;
}
duplicate = true;
group.add(DuplicateFile(AllImages_1.get(j)));
grpind.add(String.valueOf(j));
}
}
if (duplicate) {
Duplicate=true;
String Header = "Group" + Group;
modelClass = new ModelClass(group, Header);
arrayList.add(modelClass);
Group++;
}
}
}
My question: **is there an alternative solution that will achieve the same result in less time?**

Database accesses one variable correctly, but not the other

So I have two variables that I am currently trying to access. waterAmt and bucketExp. I am not certain why the waterAmt variable is working correctly but the other is not. It seems that bucketExp is not being stored the way it should, even though it is being stored the same was as waterAmt. thanks in advance for the help.
Code for accessing the database:
//pull data
data = new Database(SetupTimerPC1.this);
data.open();
bucketExpTotal = data.getBucketExp();
totalWater = data.getWaterAmt();
data.close();
//add new data to old
bucketExpTotal += bucketExp;
totalWater += waterAmt;
//push data
data.open();
data.bucketExpEntry(bucketExpTotal);
data.waterAmountEntry(totalWater);
data.close();
Code for entering waterAmt into database:
public long waterAmountEntry(int waterAmt)
{
ContentValues cv = new ContentValues();
cv.put(KEY_WATER, waterAmt);
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}//end waterAmountEntry function
Code for entering bucketExp into database:
public long bucketExpEntry(int bucketExp)
{
ContentValues cv = new ContentValues();
cv.put(KEY_BUCKETEXP, bucketExp);
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}//end bucketExpEntry function
Code for pulling waterAmt from database:
public int getWaterAmt()
{
int waterAmount = 0, iWaterAmount = 0;
String[] columns = new String[] {KEY_ROWID, KEY_ROCK, KEY_METEORROCK, KEY_WATER,
KEY_POPULATION, KEY_SHOVEL, KEY_BUCKET, KEY_PICKAXE, KEY_SHOVELEXP,
KEY_BUCKETEXP, KEY_PICKAXEEXP};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
if (c != null && c.getCount() > 0)
{
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext())
{
iWaterAmount = c.getColumnIndex(KEY_WATER);
waterAmount = c.getInt(iWaterAmount);
}//end for
c.close();
return waterAmount;
}//end if
return 0;
}//end getWaterAmt function
code for pulling bucketExp from database:
public int getBucketExp()
{
int bucketExp = 0, iBucketExp = 0;
String[] columns = new String[] {KEY_ROWID, KEY_ROCK, KEY_METEORROCK, KEY_WATER,
KEY_POPULATION, KEY_SHOVEL, KEY_BUCKET, KEY_PICKAXE, KEY_SHOVELEXP,
KEY_BUCKETEXP, KEY_PICKAXEEXP};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
if (c != null && c.getCount() > 0)
{
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext())
{
iBucketExp = c.getColumnIndex(KEY_BUCKETEXP);
bucketExp = c.getInt(iBucketExp);
}//end for
c.close();
return bucketExp;
}//end if
return 0;
}//end getBucketExp function
Right now your query amounts to this:
"SELECT [columns] FROM [table];"
This returns all the rows in your table. Next you are iterating over the entire set of results, and in each iteration you set the value to return equal to some column in the result row.
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
bucketExp = cursor.getInt(...);
}
Essentially this means bucketExp will equal the value of this column from the very last row in the results.
What I think you want is the value for a particular row/record. You need to change your query to return just the row you are looking for, and get rid of the for loop. Here's an example that will look up a specific row by an ID and return bucketExp:
public int getBucketExp(long id) {
String[] columns = new String[] { KEY_BUCKETEXP };
String where = KEY_ROWID + " = ?";
String[] whereArgs = new String[] { Long.toString(id) };
Cursor cursor = ourDatabase.query(DATABASE_TABLE, columns, where, whereArgs,
null, null, null);
int bucketExp = 0;
if (cursor.moveToFirst()) {
bucketExp = cursor.getInt(cursor.getColumnIndex(KEY_BUCKETEXP));
}
return bucketExp;
}

Looking for a appropraite logic

Actually I am using call logs as an input to database and then I am fetching it in a way that I can't get any duplicate values while displaying it and if i have any duplicate value in data base then it should be taken as integer value count. For example: john(6).
Here john must have entry 6 times in database. Don't get me wrong. I don't need a code.I need help. Here is code:
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(android.provider.CallLog.Calls.CONTENT_URI,null, null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String rawContactId = cur.getString(cur.getColumnIndex(android.provider.CallLog.Calls._ID));
Cursor callLogCursor = getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI, new String[]{
android.provider.CallLog.Calls.CACHED_NAME,
android.provider.CallLog.Calls.CACHED_NUMBER_LABEL,
android.provider.CallLog.Calls.NUMBER,
android.provider.CallLog.Calls.DATE,
android.provider.CallLog.Calls.DURATION,
android.provider.CallLog.Calls.TYPE
},android.provider.CallLog.Calls._ID + "=?", new String[] { rawContactId }, null);;
if (callLogCursor != null) {
while (callLogCursor.moveToNext()) {
//String id = callLogCursor.getString(0);
String name = callLogCursor.getString(0);
String cacheNumber = callLogCursor.getString(1);
String number = callLogCursor.getString(2);
long dateTimeMillis = callLogCursor.getLong(3);
long durationMillis = callLogCursor.getLong(4);
int callType = callLogCursor.getInt(5);
String duration = getDuration(durationMillis * 1000);
String dateString = getDateTime(dateTimeMillis);
if (cacheNumber == null)
cacheNumber = number;
if (name == null)
name = "Unknown";
Uri image = null;
try {
String conId = fetchContactIdFromPhoneNumber(cacheNumber);
long contId = Long.parseLong(conId);
image = getPhotoUri(contId);
}catch(Exception e) {
Log.e("Exception", e.getMessage());
}
//CallLogModel callLogModel = new CallLogModel(image, name, cacheNumber,
// duration, dateString);
ContentValues values = new ContentValues();
values.put(NAME, name);
values.put(NUMBER, cacheNumber);
values.put(DATE, dateString);
values.put(DURATION,duration );
database.insert(CALL_LOG_TABLE, null, values);
Cursor cursor = database.query(CALL_LOG_TABLE, new String [] {LOG_ID, NAME, NUMBER, DATE, DURATION}, null, null, null, null, null);
int row =0;
if(!cursor.isAfterLast()) {
cursor.moveToFirst();
do{
int pId=cursor.getInt(0);
String pName = cursor.getString(1);
String pNumber = cursor.getString(2);
String pDate = cursor.getString(3);
String pDuration = cursor.getString(4);
int value = 0;
CallLogModel callLogModel = new CallLogModel(image, name, cacheNumber, duration, dateString);
if (callType == CallLog.Calls.OUTGOING_TYPE) {
for(int i=0;i<outgoingList.size();i++){
------------------------------Actually i want Logic here what should i do here--------------
}
}
outgoingList.add(callLogModel);
} else if (callType == CallLog.Calls.INCOMING_TYPE) {
incomingList.add(callLogModel);
} else if (callType == CallLog.Calls.MISSED_TYPE) {
missedcallList.add(callLogModel);
}
cursor.moveToNext();
} while (!cursor.isAfterLast());
}
}
callLogCursor.close();
}
}
You could model the outgoing calls in a hashmap, something like:
Map<String, Integer> outgoingCallsMap = new HashMap<String, Integer>();
for (int i = 0; i < outgoingList.size(); i++) {
String nameOfCallee = outgoingList.get(i);
if (!outgoingCallsMap.containsKey(nameOfCallee)) {
outgoingCallsMap.put(nameOfCallee, 1);
} else {
//Increment calls to this person
outgoingCallsMap.put(nameOfCallee, outgoingCallsMap.get(nameOfCallee) + 1);
}
}
Remove the duplicates in your outGoingList, by iterating it and putting the result to a map, with contact name as key and list of CallLogModel object as value.
You can refer this method.
private void convertToOutGoingMap(List<CallLogModel > outGoingList) {
HashMap<String,List<CallLogModel>> outGoingMap = new HashMap<String, List<CallLogModel>>();//map which has CallLogModel.name as key and List<CallLogModel> as value.
for(CallLogModel model : outGoingList){//Iterate thru the list.
if(outGoingMap.containsKey(model.name))
{
outGoingMap.get(model.name).add(model);//if map contains key, add model to the list.
} else {
List<CallLogModel> modelList = new ArrayList<CallLogModel>();//if it does not contains, initialize a list and add model to it.
modelList.add(model);
outGoingMap.put(model.name, modelList);
}
}
}
}
The key set of this map gives you the unique call log names and corresponding value list gives all occurrences and its size gives you number of occurrences.
Hope this help you.

how to delete a google calendar event?

I write an android app that fetches my events,
How can I identify an event (some unique ID)
and delete it or edit it?
private void fetchEvents() {
String[] selection = new String[] { "calendar_id", "title", "description",
"dtstart", "dtend", "eventLocation" };
String projection = "description LIKE ?";
String[] selecionArgs = new String[]{"%/images/%"};
String orderby = "dtstart ASC";
Cursor cursor = getContentResolver()
.query(
Uri.parse("content://com.android.calendar/events"),
selection, projection,
selecionArgs, orderby);
cursor.moveToFirst();
// fetching calendars name
String CNames[] = new String[cursor.getCount()];
// fetching calendars id
nameOfEvent.clear();
startDates.clear();
endDates.clear();
descriptions.clear();
for (int i = 0; i < CNames.length; i++) {
nameOfEvent.add(cursor.getString(1));
startDates.add(new Date(Long.parseLong(cursor.getString(3))));
//endDates.add(new Date(Long.parseLong(cursor.getString(4))));
String fullDescription = cursor.getString(2);
int firstIndex = fullDescription.indexOf("localUri: ");
firstIndex = (firstIndex < 0)? 0 : 10;
int lastIndex = fullDescription.indexOf("\n");
lastIndex = (lastIndex < 0)? fullDescription.length() : lastIndex;
descriptions.add(fullDescription.substring(firstIndex, lastIndex));
CNames[i] = cursor.getString(1);
cursor.moveToNext();
}
}

How to get the contact group id or name?

I can't get the group name under which the contact is stored. I can get whether it is added in any group as boolean value( IN_VISIBLE_GROUP).I have no idea how to get the group name or id.
ContentResolver cr = this.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext())
{
id = cur.getString(cur
.getColumnIndex(BaseColumns._ID));
String name = cur
.getString(cur
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String group = cur
.getString(cur
.getColumnIndex(ContactsContract.Contacts.IN_VISIBLE_GROUP));
i have tried using ContactsContract.Groups and ContactsContract.Groups and ContactsContract.CommonDataKinds.GroupMembership but that is not the solution.
This is a full version of how to get the group id by its title. Basically it iterates all groups and compare titles to find its id.
private String getGroupId(String groupTitle) {
Cursor cursor =getContentResolver().query(ContactsContract.Groups.CONTENT_URI,new String[]{ContactsContract.Groups._ID,ContactsContract.Groups.TITLE}, null, null, null);
cursor.moveToFirst();
int len = cursor.getCount();
String groupId = null;
for (int i = 0; i < len; i++) {
String id = cursor.getString(cursor.getColumnIndex(Groups._ID));
String title = cursor.getString(cursor.getColumnIndex(Groups.TITLE));
if (title.equals(groupTitle)) {
groupId = id;
break;
}
cursor.moveToNext();
}
cursor.close();
return groupId;
}
Please change
ContentResolver cr = this.getContentResolver();
to
Uri groupURI = ContactsContract.Data.CONTENT_URI;
Cursor cur = cr.query(groupURI , null, null, null, null);
// Now you can get group ID from cursor
String groupRowId = cur.getString (cur.getColumnIndex(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID));
public Integer getGroupId(String groupTitle) {
String[] PROJECTION = {ContactsContract.Groups._ID};
String SELECTION = ContactsContract.Groups.TITLE + "=?";
try (Cursor cursor = mContentResolver.query(ContactsContract.Groups.CONTENT_URI,
PROJECTION, SELECTION, new String[]{groupTitle}, null)) {
if (cursor.getCount()>0){
cursor.moveToFirst();
Integer id= cursor.getInt(0);
return id;
}else
return 0;
}
}

Categories