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で測定した:
たとえどんな卑猥な方法を採用したとしても、mStrictをfalseに設定して、selecitonは次のスプライト過程で括弧で補填される可能性があります。
簡単に見ましたが、この修正はICSの変更説明に記載されていません。googleにとっては単なるバグです。
もしクラスメートのアプリがこのような方法を使ったら、ICSの下で互換性を変えます。
問題そのものに戻って、どのようにContentProviderの中でgroupbyを実現しますか?もし、このContentProviderは自分で実現しますか?あるいはシステムを修正することができるプロバイダーです。できます。SQLiteQueryBuider類はgroupbyのqueryインターフェースを提供します。
ContectProviderはCalllogProvider、Contacts Providerのように、直接に調べる方法はないと知っています。代わりにMatrixCrsor類を使って、まずすべてのデータを調べてから、Cursorを経由して、MatrixCurorを自分で処理します。これはMatrixCurerの接続効率が高いです。アルゴリズムの最適化と非同期処理が必要です。
参考文献:
http://yelinsen.iteye.com/blog/836935
http://www.eoeandroid.com/thread-31662-1-1.html
例えば、このような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