18e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki/*
2654888562d75fe4758cb0500f73aaa11385e6f63Makoto Onuki * Copyright (C) 2011 The Android Open Source Project
38e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki *
48e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
58e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * you may not use this file except in compliance with the License.
68e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * You may obtain a copy of the License at
78e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki *
88e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
98e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki *
108e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * Unless required by applicable law or agreed to in writing, software
118e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
128e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * See the License for the specific language governing permissions and
148e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * limitations under the License.
158e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki */
168e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
178e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukipackage com.android.contacts.tests;
188e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
198e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukiimport android.app.IntentService;
208e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukiimport android.content.Intent;
218e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukiimport android.database.Cursor;
228e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukiimport android.net.Uri;
23953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onukiimport android.text.TextUtils;
248e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukiimport android.util.Log;
258e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
268e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki/**
278e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * A service that executes a query specified by an intent and dump the result on logcat.  Use the
288e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki * "am" command to launch it.
298e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki *
308e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki   Usage:
318e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki     adb shell am startservice -d URI \
32953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki       [-e p OPTIONAL PROJECTION] [-e s OPTIONAL SELECTION] [-e s OPTIONAL ORDER BY]  \
338e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki       com.android.contacts.tests/.QueryService
348e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
358e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki   Example:
368e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
378e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki   adb shell am startservice -d content://com.android.contacts/directories \
38953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki     -e p accountName,accountType -e s 'accountName NOT NULL' -e o '_id'  \
398e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki     com.android.contacts.tests/.QueryService
408e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki */
418e34744e041e3db61aa3544b03594e5b379c946cMakoto Onukipublic class QueryService extends IntentService {
428e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    private static final String TAG = "contactsquery";
438e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
44953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki    private static final String EXTRA_PROJECTION = "p";
458e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    private static final String EXTRA_SELECTION = "s";
468e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    private static final String EXTRA_ORDER = "o";
478e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    private static final String NULL_STRING = "*null*";
488e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    private static final String SEPARATOR = "|";
498e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
508e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    public QueryService() {
518e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        super("ContactsQueryService");
528e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    }
538e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
548e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    @Override
558e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    protected void onHandleIntent(Intent intent) {
568e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        final Uri uri = intent.getData();
57953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        // Unfortunately "am" doesn't support string arrays...
58953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        final String projection = intent.getStringExtra(EXTRA_PROJECTION);
598e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        final String selection = intent.getStringExtra(EXTRA_SELECTION);
608e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        final String order = intent.getStringExtra(EXTRA_ORDER);
618e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
628e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        Log.i(TAG, "URI: " + uri);
63953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        Log.i(TAG, "Projection: " + projection);
648e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        Log.i(TAG, "Selection: " + selection);
658e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
668e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        try {
67953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            Cursor c = getContentResolver().query(uri, parseProjection(projection), selection, null,
68953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                    order);
69953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            if (c == null) {
70953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                Log.i(TAG, "(no results)");
71953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                return;
728e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki            }
73953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            StringBuilder sb = new StringBuilder();
74953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            try {
75953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                Log.i(TAG, "Result count: " + c.getCount());
76953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki
77953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                final int columnCount = c.getColumnCount();
788e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
798e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki                sb.setLength(0);
808e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki                for (int i = 0; i < columnCount; i++) {
81953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                    add(sb, c.getColumnName(i));
828e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki                }
838e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki                Log.i(TAG, sb.toString());
84953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki
85953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                c.moveToPosition(-1);
86953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                while (c.moveToNext()) {
87953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                    sb.setLength(0);
88953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                    for (int i = 0; i < columnCount; i++) {
89953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                        add(sb, c.getString(i));
90953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                    }
91953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                    Log.i(TAG, sb.toString());
92953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                }
93953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            } finally {
94953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki                c.close();
958e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki            }
96953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        } catch (Exception e) {
97953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            Log.e(TAG, "Exeption while executing query", e);
988e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        }
998e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    }
1008e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki
1018e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    private StringBuilder add(StringBuilder sb, String s) {
1028e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        if (sb.length() > 0) {
1038e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki            sb.append(SEPARATOR);
1048e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        }
1058e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        sb.append(s == null ? NULL_STRING : s);
1068e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki        return sb;
1078e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki    }
108953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki
109953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki    private static String[] parseProjection(String projectionString) {
110953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        if (TextUtils.isEmpty(projectionString)) {
111953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            return null; // all columns
112953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        }
113953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        final String[] columns = projectionString.split(",");
114953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        if (columns.length == 0) {
115953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki            return null; // all columns
116953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        }
117953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki        return columns;
118953dc0c8c95e0b7c3aabcaacea0b6e88d3174462Makoto Onuki    }
1198e34744e041e3db61aa3544b03594e5b379c946cMakoto Onuki}
120