ContentProviderによるグループバイクエリデータ(転送)およびICS後の修正(元)を実現します。


多くの人がContentproviderのquery方法の中でgroupbyを使って調べたいですが、どうやってSDKの中でこのような機能を提供しないのですか?そこで、ある牛はハッカーの注入式からヒントを得て、やり方は以下の通りです。
例えば、このようなsql文を実現するために使用します。id,number,date,duration,type,name,numbertype,numbelabel,COUNT(*)FROM cals  GROUTP BY number、type、date/8640000 ORDER BY date DESCこれが一般的なSQLコンパイルツールで正常に動作すると、ContentRosoverではちょっと違っています。ContentRosoverの中のqueryでこう書きます。prvate static String CALLS_COUNT=「calsount」static final String[]CALL_LOG_PROJECTION=new String[]           Calls._ID、           Calls.NUMBER、           Calls.DATE           Calls.DURATION、           Calls.TYPE、           Calls.C.ACHEDHum           Calls.C.ACHEDUNUMBERUTYPE、           Calls.C.ACHEDUNUMBERHuLABEL、           「COUNT(*)AS」+CALLSCOUNT   }; Steringセレクション="0==0)GROUT BY("+           Calls.NUMBER+“),(”+           Calls.TYPE+“),(”+           Calls.DATE+「/8640000」、rororover.query(QUEURY-uTOKEN、null、Calls.C.ONTTEURI、               CALLUGuPROJECTION、セレクション、null、Calls.DEFAULT_SORTUORDER;注意事項:1キーワード「COUNT、AS、GROUT BY」の大きさは2 COUNT(*)を書いた後、AS*3 Androidと一緒にqueryのパラメータを一つの文にまとめます。の形式ですので、セレクションに括弧がある場合は、4 GROUT BYの後ろのフィールドに括弧を入れて、カンマで区切らなければなりません。sql文に変換する正しい形式は、次のようになります。SELECT_id、number、date、type、name、numberge、nbell、COUNT(*)FRcarbers WHERE=DEDEDEDEORTS
==================線を分割========================================================================
残念です。ICSでは、この方法はまた適用されませんでした。
ソースコードを追跡した後、ICSの対応プロバイダー(例えば、CalllogProvider)とFrame eworkのSQLiteQueryBuider類は、この脆弱性を補いました。
まず一つのパラメータmStrictを追加しました。CalllogProviderのquery方法でtrueに設定されています。
SQLiteQueryBuiderで測定した:
 private String[] computeProjection(String[] projectionIn) {
        if (projectionIn != null && projectionIn.length > 0) {
            if (mProjectionMap != null) {
                String[] projection = new String[projectionIn.length];
                int length = projectionIn.length;


                for (int i = 0; i < length; i++) {
                    String userColumn = projectionIn[i];
                    String column = mProjectionMap.get(userColumn);


                    if (column != null) {
                        projection[i] = column;
                        continue;
                    }

		 
                    if (!mStrict &&
                            ( userColumn.contains(" AS ") || userColumn.contains(" as "))) {
                        /* A column alias already exist */
                        projection[i] = userColumn;
                        continue;
                    }


                    throw new IllegalArgumentException("Invalid column "
                            + projectionIn[i]);
                }
                return projection;
            } else {
                return projectionIn;
            }
        } else if (mProjectionMap != null) {
            // Return all columns in projection map.
            Set<Entry<String, String>> entrySet = mProjectionMap.entrySet();
            String[] projection = new String[entrySet.size()];
            Iterator<Entry<String, String>> entryIter = entrySet.iterator();
            int i = 0;


            while (entryIter.hasNext()) {
                Entry<String, String> entry = entryIter.next();


                // Don't include the _count column when people ask for no projection.
                if (entry.getKey().equals(BaseColumns._COUNT)) {
                    continue;
                }
                projection[i++] = entry.getValue();
            }
            return projection;
        }
         return null;
    }
レッドの前と後のコードから見られます。自分で定義したプロモーションの中のコロンはそのまま投げられました。
たとえどんな卑猥な方法を採用したとしても、mStrictをfalseに設定して、selecitonは次のスプライト過程で括弧で補填される可能性があります。
簡単に見ましたが、この修正はICSの変更説明に記載されていません。googleにとっては単なるバグです。
もしクラスメートのアプリがこのような方法を使ったら、ICSの下で互換性を変えます。
問題そのものに戻って、どのようにContentProviderの中でgroupbyを実現しますか?もし、このContentProviderは自分で実現しますか?あるいはシステムを修正することができるプロバイダーです。できます。SQLiteQueryBuider類はgroupbyのqueryインターフェースを提供します。
public Cursor query(SQLiteDatabase db, String[] projectionIn,
            String selection, String[] selectionArgs, String groupBy,
            String having, String sortOrder, String limit) 
もし、システムを使うなら
ContectProviderはCalllogProvider、Contacts Providerのように、直接に調べる方法はないと知っています。代わりにMatrixCrsor類を使って、まずすべてのデータを調べてから、Cursorを経由して、MatrixCurorを自分で処理します。これはMatrixCurerの接続効率が高いです。アルゴリズムの最適化と非同期処理が必要です。
参考文献:
http://yelinsen.iteye.com/blog/836935
http://www.eoeandroid.com/thread-31662-1-1.html