DatabaseUtils: java.lang.IllegalArgumentException: Invalid token LIMIT

一、前言

在Android12上遇到了一个错误,这里解决了一部分。在使用ContentResolve时候遇到以下错误

DatabaseUtils: java.lang.IllegalArgumentException: Invalid token LIMIT

在解决过程中参考了以下重要链接:
https://blog.csdn.net/u010471406/article/details/118112086。
经过测试,数据库的使用,比如SQLiteOpenHelper的常规使用是不会引起这个问题的。
在以下链接里面提供了另外一种解决方式:
https://stackoverflow.com/questions/66280961/contentresolver-query-method-throws-invalid-token-limit-error

二、解决代码

经过上述链接其中关于查询语句中的limit的限制提供了解决方式,现在将代码进行整理。原代码是关于查询电话记录错误。这里借鉴下作者的代码:

     /**
         * Get if the query is marked as strict, as last configured by
         * {@link #setStrictGrammar(boolean)}.
         */
        public static String getLastOutgoingCall(Context context) {
    
    
            final ContentResolver resolver = context.getContentResolver();
            Cursor c = null;
            try {
    
    
                c = resolver.query(Calls.CONTENT_URI,
                                   new String[] {
    
    
                                       Calls.NUMBER
                                   }, Calls.TYPE + " = "
                                   + Calls.OUTGOING_TYPE, null,
                                   Calls.DEFAULT_SORT_ORDER + " LIMIT 1");
                if (c == null || !c.moveToFirst()) {
    
    
                    return "";
                }
                return c.getString(0);
            } finally {
    
    
                if (c != null)
                    c.close();
            }
        }

上述代码执行过程中会出现问题,修改后的代码如下


        /**
         * Get if the query is marked as strict, as last configured by
         * {@link #setStrictGrammar(boolean)}.
         */
        public static String getLastOutgoingCall(Context context) {
    
    
            final ContentResolver resolver = context.getContentResolver();
            Cursor c = null;
            try {
    
    
            Uri limitedCallLogUri = CallLog.Calls.CONTENT_URI.buildUpon()
        .appendQueryParameter(CallLog.Calls.LIMIT_PARAM_KEY, "1").build();
                c = resolver.query(limitedCallLogUri,
                                   new String[] {
    
    
                                       Calls.NUMBER
                                   }, Calls.TYPE + " = "
                                   + Calls.OUTGOING_TYPE, null,
                                   Calls.DEFAULT_SORT_ORDER + " LIMIT 1");
                if (c == null || !c.moveToFirst()) {
    
    
                    return "";
                }
                return c.getString(0);
            } finally {
    
    
                if (c != null)
                    c.close();
            }
        }
        

该代码经过查证其实是可以做成通用代码的,其中CallLog.Calls.CONTENT_URI可以替换成任意UriCallLog.Calls.LIMIT_PARAM_KEY可以替换成ContactsContract.LIMIT_PARAM_KEY。经过查证在ContactsContract类中有相关代码示例:

 /**
         * <p>
         * A <i>read-only</i> sub-directory of a single contact aggregate that
         * contains all aggregation suggestions (other contacts). The
         * aggregation suggestions are computed based on approximate data
         * matches with this contact.
         * </p>
         * <p>
         * <i>Note: this query may be expensive! If you need to use it in bulk,
         * make sure the user experience is acceptable when the query runs for a
         * long time.</i>
         * <p>
         * Usage example:
         *
         * <pre>
         * Uri uri = Contacts.CONTENT_URI.buildUpon()
         *          .appendEncodedPath(String.valueOf(contactId))
         *          .appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY)
         *          .appendQueryParameter(&quot;limit&quot;, &quot;3&quot;)
         *          .build()
         * Cursor cursor = getContentResolver().query(suggestionsUri,
         *          new String[] {Contacts.DISPLAY_NAME, Contacts._ID, Contacts.LOOKUP_KEY},
         *          null, null, null);
         * </pre>
         *
         * </p>
         * <p>
         * This directory can be used either with a {@link #CONTENT_URI} or
         * {@link #CONTENT_LOOKUP_URI}.
         * </p>
         */

end…

三、拓展

在Android11之上使用ContentResolver时候,官方不在推荐使用sql语句的方式去查询,推荐使用Bundle的方式,其参考代码在官方API里面有示例代码,链接如下:
https://developer.android.com/reference/android/content/ContentProvider#query(android.net.Uri,%20java.lang.String[],%20android.os.Bundle,%20android.os.CancellationSignal)

这里将官方的示例代码贴出,不过只是部分的详细参数部分,还需去查阅官方

 Bundle queryArgs = new Bundle();
 queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 30);
 queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 20);
 
 Cursor cursor = getContentResolver().query(
         contentUri,    // Content Uri is specific to individual content providers.
         projection,    // String[] describing which columns to return.
         queryArgs,     // Query arguments.
         null);         // Cancellation signal.

四、参考链接

  1. ContentProvider
  2. https://stackoverflow.com/questions/66280961/contentresolver-query-method-throws-invalid-token-limit-error
  3. https://blog.csdn.net/u010471406/article/details/118112086

猜你喜欢

转载自blog.csdn.net/Mr_Tony/article/details/125996836