2 * ownCloud Android client application
4 * @author David A. Velasco
5 * Copyright (C) 2015 ownCloud Inc.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2,
9 * as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 package com
.owncloud
.android
.providers
;
24 import android
.accounts
.Account
;
25 import android
.app
.SearchManager
;
26 import android
.content
.ContentProvider
;
27 import android
.content
.ContentValues
;
28 import android
.content
.UriMatcher
;
29 import android
.database
.Cursor
;
30 import android
.database
.MatrixCursor
;
31 import android
.net
.Uri
;
32 import android
.os
.Handler
;
33 import android
.os
.Looper
;
34 import android
.provider
.BaseColumns
;
35 import android
.support
.annotation
.Nullable
;
36 import android
.widget
.Toast
;
38 import com
.owncloud
.android
.R
;
39 import com
.owncloud
.android
.authentication
.AccountUtils
;
40 import com
.owncloud
.android
.lib
.common
.operations
.RemoteOperationResult
;
41 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
;
42 import com
.owncloud
.android
.lib
.resources
.shares
.GetRemoteShareesOperation
;
43 import com
.owncloud
.android
.utils
.ErrorMessageAdapter
;
45 import org
.json
.JSONException
;
46 import org
.json
.JSONObject
;
48 import java
.util
.ArrayList
;
49 import java
.util
.Iterator
;
50 import java
.util
.List
;
54 * Content provider for search suggestions, to search for users and groups existing in an ownCloud server.
56 public class UsersAndGroupsSearchProvider
extends ContentProvider
{
58 private static final String TAG
= UsersAndGroupsSearchProvider
.class.getSimpleName();
60 private static final String
[] COLUMNS
= {
62 SearchManager
.SUGGEST_COLUMN_TEXT_1
,
63 SearchManager
.SUGGEST_COLUMN_INTENT_DATA
66 private static final int SEARCH
= 1;
68 private static final int RESULTS_PER_PAGE
= 50;
69 private static final int REQUESTED_PAGE
= 1;
71 public static final String AUTHORITY
= UsersAndGroupsSearchProvider
.class.getCanonicalName();
72 public static final String ACTION_SHARE_WITH
= AUTHORITY
+ ".action.SHARE_WITH";
73 public static final String DATA_USER
= AUTHORITY
+ ".data.user";
74 public static final String DATA_GROUP
= AUTHORITY
+ ".data.group";
76 private UriMatcher mUriMatcher
;
80 public String
getType(Uri uri
) {
86 public boolean onCreate() {
87 mUriMatcher
= new UriMatcher(UriMatcher
.NO_MATCH
);
88 mUriMatcher
.addURI(AUTHORITY
, SearchManager
.SUGGEST_URI_PATH_QUERY
+ "/*", SEARCH
);
95 * Reference: http://developer.android.com/guide/topics/search/adding-custom-suggestions.html#CustomContentProvider
97 * @param uri Content {@link Uri}, formattted as
98 * "content://com.owncloud.android.providers.UsersAndGroupsSearchProvider/" +
99 * {@link android.app.SearchManager#SUGGEST_URI_PATH_QUERY} + "/" + 'userQuery'
100 * @param projection Expected to be NULL.
101 * @param selection Expected to be NULL.
102 * @param selectionArgs Expected to be NULL.
103 * @param sortOrder Expected to be NULL.
104 * @return Cursor with users and groups in the ownCloud server that match 'userQuery'.
108 public Cursor
query(Uri uri
, String
[] projection
, String selection
, String
[] selectionArgs
, String sortOrder
) {
109 Log_OC
.d(TAG
, "query received in thread " + Thread
.currentThread().getName());
111 int match
= mUriMatcher
.match(uri
);
114 return searchForUsersOrGroups(uri
);
121 private Cursor
searchForUsersOrGroups(Uri uri
) {
122 MatrixCursor response
= null
;
125 String userQuery
= uri
.getLastPathSegment().toLowerCase();
128 /// need to trust on the AccountUtils to get the current account since the query in the client side is not
129 /// directly started by our code, but from SearchView implementation
130 Account account
= AccountUtils
.getCurrentOwnCloudAccount(getContext());
132 /// request to the OC server about users and groups matching userQuery
133 GetRemoteShareesOperation searchRequest
= new GetRemoteShareesOperation(
134 userQuery
, REQUESTED_PAGE
, RESULTS_PER_PAGE
136 RemoteOperationResult result
= searchRequest
.execute(account
, getContext());
137 List
<JSONObject
> names
= new ArrayList
<JSONObject
>();
138 if (result
.isSuccess()) {
139 for (Object o
: result
.getData()) {
140 // Get JSonObjects from response
141 names
.add((JSONObject
) o
);
144 showErrorMessage(result
);
147 /// convert the responses from the OC server to the expected format
148 if (names
.size() > 0) {
149 response
= new MatrixCursor(COLUMNS
);
150 Iterator
<JSONObject
> namesIt
= names
.iterator();
155 Uri userBaseUri
= new Uri
.Builder().scheme("content").authority(DATA_USER
).build();
156 Uri groupBaseUri
= new Uri
.Builder().scheme("content").authority(DATA_GROUP
).build();
158 while (namesIt
.hasNext()) {
159 item
= namesIt
.next();
160 String userName
= item
.getString(GetRemoteShareesOperation
.PROPERTY_LABEL
);
161 JSONObject value
= item
.getJSONObject(GetRemoteShareesOperation
.NODE_VALUE
);
162 byte type
= (byte) value
.getInt(GetRemoteShareesOperation
.PROPERTY_SHARE_TYPE
);
163 String shareWith
= value
.getString(GetRemoteShareesOperation
.PROPERTY_SHARE_WITH
);
164 if (GetRemoteShareesOperation
.GROUP_TYPE
.equals(type
)) {
165 displayName
= getContext().getString(R
.string
.share_group_clarification
, userName
);
166 dataUri
= Uri
.withAppendedPath(groupBaseUri
, shareWith
);
168 displayName
= userName
;
169 dataUri
= Uri
.withAppendedPath(userBaseUri
, shareWith
);
172 .add(count
++) // BaseColumns._ID
173 .add(displayName
) // SearchManager.SUGGEST_COLUMN_TEXT_1
176 } catch (JSONException e
) {
177 Log_OC
.e(TAG
, "Exception while parsing data of users/groups", e
);
186 public Uri
insert(Uri uri
, ContentValues values
) {
187 // TODO implementation
192 public int delete(Uri uri
, String selection
, String
[] selectionArgs
) {
193 // TODO implementation
198 public int update(Uri uri
, ContentValues values
, String selection
, String
[] selectionArgs
) {
199 // TODO implementation
206 * @param result Result with the failure information.
208 public void showErrorMessage(final RemoteOperationResult result
) {
209 Handler handler
= new Handler(Looper
.getMainLooper());
210 handler
.post(new Runnable() {
213 // The Toast must be shown in the main thread to grant that will be hidden correctly; otherwise
214 // the thread may die before, an exception will occur, and the message will be left on the screen
215 // until the app dies
217 getContext().getApplicationContext(),
218 ErrorMessageAdapter
.getErrorCauseMessage(
221 getContext().getResources()