Android Question ContentResolver error : "Invalid token limit"

drgottjr

Expert
Licensed User
Longtime User
the current version of the contentresolver does not
support the version of query() you're referring to.

if you're relatively comfortable with java, but you
don't know yet how to use javaobject in b4a to run
java methods from b4a, i can tell you it's not
difficult to do.

below is a snippet of how you might query the
database with limit and offset constraints from b4a.
it would, for example, query a listing of your files in
the gallery folder with a limit and offset set. see if
it looks like something you could handle. i have no
idea what it is you're looking to do.


B4X:
Sub Activity_Create(FirstTime As Boolean)
    Dim jo As JavaObject
    jo.InitializeContext
    ' list 10 files starting at offset 0
    jo.RunMethod("listInGalleryWithLimitAndOffset", Array( 10, 0 ))
End Sub

#if Java
   //  imports go here   ...
  
   public void listInGalleryWithLimitAndOffset(int limit, int offset) {
    String[] projections = { MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media._ID,MediaStore.Images.Media.DATA };
    Bundle bundle = new Bundle();
    bundle.putInt(ContentResolver.QUERY_ARG_OFFSET, offset);
    bundle.putInt(ContentResolver.QUERY_ARG_LIMIT, limit);
    Cursor mCursor = getContentResolver()
    .query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                projections,
                  bundle,
                  null);

    BA.Log( MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString());
    BA.Log( mCursor.getCount() + " found.");

    // more code ...  (eg, actually listing the files)
#End If
 
Upvote 0

S.M.R

Member
the current version of the contentresolver does not
support the version of query() you're referring to.

if you're relatively comfortable with java, but you
don't know yet how to use javaobject in b4a to run
java methods from b4a, i can tell you it's not
difficult to do.

below is a snippet of how you might query the
database with limit and offset constraints from b4a.
it would, for example, query a listing of your files in
the gallery folder with a limit and offset set. see if
it looks like something you could handle. i have no
idea what it is you're looking to do.


B4X:
Sub Activity_Create(FirstTime As Boolean)
    Dim jo As JavaObject
    jo.InitializeContext
    ' list 10 files starting at offset 0
    jo.RunMethod("listInGalleryWithLimitAndOffset", Array( 10, 0 ))
End Sub

#if Java
   //  imports go here   ...
 
   public void listInGalleryWithLimitAndOffset(int limit, int offset) {
    String[] projections = { MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media._ID,MediaStore.Images.Media.DATA };
    Bundle bundle = new Bundle();
    bundle.putInt(ContentResolver.QUERY_ARG_OFFSET, offset);
    bundle.putInt(ContentResolver.QUERY_ARG_LIMIT, limit);
    Cursor mCursor = getContentResolver()
    .query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                projections,
                  bundle,
                  null);

    BA.Log( MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString());
    BA.Log( mCursor.getCount() + " found.");

    // more code ...  (eg, actually listing the files)
#End If
Thanks for your help,

i want get call list from :
"content://call_log/calls"

can you get me ?
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
have you tried anything? what have you done so far with the contentresolver library? show code
 
Upvote 0

S.M.R

Member
have you tried anything? what have you done so far with the contentresolver library? show code
get call list with content resolver:
Dim URI As Uri
    Dim Query As Cursor
    Dim CR As ContentResolver
    Dim LS As List

    LS.Initialize
    CR.Initialize("")
    
    URI.Parse("content://call_log/calls")
    
    If Limit = 0 Then
        Limit = -1
    End If
    
    Query = CR.Query(URI, Array As String(),"",Null,"date DESC LIMIT " & Limit)
    
'    نمایش کل فیلدهای جدول
'    printCursor(Query)

    For i = 0 To Query.RowCount-1
        Query.Position = i
        
        Dim Ci As CallLog_iTem
        Ci.Initialize
        Ci.CachedName = Query.GetString("name")
        Ci.CallType = Query.GetString("type")
        Ci.Date = Query.GetString("date")
        Ci.Duration = Query.GetString("duration")
        Ci.Id = Query.GetString("_id")
        Ci.Number = Query.GetString("number")
        Ci.subscription_id = Query.GetString("subscription_id")
        
        LS.Add(Ci)
    Next
    
    Return LS



Problem : LIMIT not work on android 11
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i have no problem accessing the call log through the contentresolver, android 12, sdk 30. this is what this thread is about.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
Accessing "content://call_log/calls" requires the CALL_LOG permission.
yes, and i am about to post my example for the OP. not only is the manifest permission required, but device settings must be set as well. have faith! i'm posting it now.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i have no interest in the call log, but i can access it
with the limit and offset constraints you want using
the contentresolver, not the contentresolver
library. as i mentioned, the library uses a different
query() method than the one you need to use the
limit and offset constraints (at least according to
SO). you can access the contentresolver api
directly in java and with a javaobject in b4a to run
the necessary version of query().

please copy the permissions to the manifest:

B4X:
AddPermission(android.permission.READ_CALL_LOG)
AddPermission(android.permission.READ_CONTACTS)


IN ADDITION: you need to access the permission manager
in your device's settings (capture2.png, attached), once the
app has been deployed. this is new.

add this to your b4a code: (as in capture.png, attached)

B4X:
    Dim jo As JavaObject
    jo.InitializeContext
    jo.RunMethod("callLog", Array(10,0))




at the end of your app, add the inline java code:

B4X:
#if Java
    import android.content.Context;
    import android.content.ContentResolver;
    import android.provider.MediaStore;
    import android.database.Cursor;
    import android.provider.MediaStore.Images.Media;
    import android.provider.MediaStore.MediaColumns;
    import android.content.res.AssetFileDescriptor;
    import android.content.ContentValues;
    import android.net.Uri;
    import android.content.res.AssetManager;
    import android.provider.CallLog;
    import android.provider.CallLog.Calls;
   
    import java.io.IOException;
    import java.util.*;
    import java.lang.String;

    import android.os.Build.VERSION;
    import android.os.Build.VERSION_CODES;
    import android.os.Bundle;


   public void callLog(int limit, int offset) {
 
                   if ( (limit < 1) || (offset < 0) ) {
                    BA.Log("limit and offset required");
                    return;
                 }
 
    Bundle bundle = new Bundle();
    bundle.putInt(ContentResolver.QUERY_ARG_OFFSET, offset);
    bundle.putInt(ContentResolver.QUERY_ARG_LIMIT, limit);
    bundle.putString(ContentResolver.QUERY_ARG_SORT_DIRECTION,CallLog.Calls.DATE + " DESC");    // if unspecified, it's supposed to default to default...

    Cursor cursor = getContentResolver()
    .query(
        Uri.parse("content://call_log/calls"),  // Uri
        null,                                   // projection
        bundle,                                   // bundle  limit and offset
        null);                                   // cancellation


    BA.Log( cursor.getCount() + " found.");

    cursor.moveToFirst();
    int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
    int type = cursor.getColumnIndex(CallLog.Calls.TYPE);
    int date = cursor.getColumnIndex(CallLog.Calls.DATE);
    int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);      

        while(!cursor.isAfterLast()) {
           String phNumber = cursor.getString(number);
           String callDate = cursor.getString(date);
           java.util.Date time = new java.util.Date(Long.parseLong(callDate));
           BA.Log(phNumber + " " + time);
           cursor.moveToNext();
        }
        cursor.close();
   }

 #end if

note: not all of the imports are necessary. they belong to some other code
i was using. i changed some of that code to access the call log, but i left
the imports that were already there. they won't hurt, and they can be removed
later. i also only show a couple fields available. that can also be changed.
let's see what you get when you try the routine. it works on my test device
running android 12 and sdk30.

oh, by the way, i only have 1 call on my test device, so i couldn't actually test
the limit and offset. you'll see what you get.
 

Attachments

  • capture.PNG
    capture.PNG
    10.9 KB · Views: 165
  • capture2.png
    capture2.png
    42.5 KB · Views: 186
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
The only problem with this permission is that your app will not be accepted to Google Play.
OP didn't mention play, but i think he has to write the letter. who knows how great his app is? (especially when it depends completely on my contribution!)
 
Upvote 0
Top