blob: 6560ad0b6ed8c867c085bc3fdaed9c9e15dab1e0 [file] [log] [blame]
Walter Jangcab3dce2015-02-09 17:48:03 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.contacts.editor;
18
19import com.android.contacts.R;
20import com.android.contacts.common.model.AccountTypeManager;
21import com.android.contacts.common.model.RawContactDelta;
22import com.android.contacts.common.model.RawContactDeltaList;
Walter Jange720fde2015-02-17 10:54:14 -080023import com.android.contacts.common.model.RawContactModifier;
Walter Jangcab3dce2015-02-09 17:48:03 -080024import com.android.contacts.common.model.ValuesDelta;
25import com.android.contacts.common.model.account.AccountType;
26import com.android.contacts.common.model.account.AccountType.EditField;
27import com.android.contacts.common.model.dataitem.DataKind;
Walter Jangf46abd82015-02-20 16:52:04 -080028import com.android.contacts.common.util.MaterialColorMapUtils;
Walter Jang3efae4a2015-02-18 11:12:00 -080029import com.android.contacts.editor.CompactContactEditorFragment.PhotoHandler;
Walter Jangcab3dce2015-02-09 17:48:03 -080030
31import android.content.Context;
Walter Jang3efae4a2015-02-18 11:12:00 -080032import android.graphics.Bitmap;
Walter Jangcab3dce2015-02-09 17:48:03 -080033import android.provider.ContactsContract.CommonDataKinds.Email;
34import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
Walter Jang3efae4a2015-02-18 11:12:00 -080035import android.provider.ContactsContract.CommonDataKinds.Nickname;
Walter Jangcab3dce2015-02-09 17:48:03 -080036import android.provider.ContactsContract.CommonDataKinds.Phone;
37import android.provider.ContactsContract.CommonDataKinds.Photo;
Walter Jangcab3dce2015-02-09 17:48:03 -080038import android.provider.ContactsContract.CommonDataKinds.StructuredName;
39import android.text.TextUtils;
40import android.util.AttributeSet;
41import android.util.Log;
42import android.view.LayoutInflater;
Walter Jangb1c87622015-02-13 17:51:38 -080043import android.view.View;
Walter Jangcab3dce2015-02-09 17:48:03 -080044import android.view.ViewGroup;
45import android.widget.LinearLayout;
46
47import java.util.ArrayList;
48import java.util.List;
49
50/**
51 * View to display information from multiple {@link RawContactDelta}s grouped together
52 * (e.g. all the phone numbers from a {@link com.android.contacts.common.model.Contact} together.
53 */
Walter Jangb6ca2722015-02-20 11:10:25 -080054public class CompactRawContactsEditorView extends LinearLayout implements View.OnClickListener {
Walter Jangcab3dce2015-02-09 17:48:03 -080055
56 private static final String TAG = "CompactEditorView";
57
Walter Jangb6ca2722015-02-20 11:10:25 -080058 /**
59 * Callbacks for hosts of {@link CompactRawContactsEditorView}s.
60 */
61 public interface Listener {
62
63 /**
64 * Invoked when the compact editor should be expanded to show all fields.
65 */
66 public void onExpandEditor();
67 }
68
69 private Listener mListener;
70
Walter Jangcab3dce2015-02-09 17:48:03 -080071 private AccountTypeManager mAccountTypeManager;
72 private LayoutInflater mLayoutInflater;
73 private ViewIdGenerator mViewIdGenerator;
Walter Jangf46abd82015-02-20 16:52:04 -080074 private MaterialColorMapUtils.MaterialPalette mMaterialPalette;
Walter Jangcab3dce2015-02-09 17:48:03 -080075
Walter Jang3efae4a2015-02-18 11:12:00 -080076 private CompactHeaderView mHeader;
Walter Jangcab3dce2015-02-09 17:48:03 -080077 private ViewGroup mNames;
Walter Jangb1c87622015-02-13 17:51:38 -080078 private ViewGroup mPhoneticNames;
79 private ViewGroup mNicknames;
Walter Jangcab3dce2015-02-09 17:48:03 -080080 private ViewGroup mPhoneNumbers;
81 private ViewGroup mEmails;
82 private ViewGroup mOther;
Walter Jangb6ca2722015-02-20 11:10:25 -080083 private View mMoreFields;
Walter Jangcab3dce2015-02-09 17:48:03 -080084
Walter Jang3efae4a2015-02-18 11:12:00 -080085 // TODO: remove this after we handle account selection for photos
86 private long mPhotoRawContactId;
87
Walter Jangcab3dce2015-02-09 17:48:03 -080088 public CompactRawContactsEditorView(Context context) {
89 super(context);
90 }
91
92 public CompactRawContactsEditorView(Context context, AttributeSet attrs) {
93 super(context, attrs);
94 }
95
Walter Jangb6ca2722015-02-20 11:10:25 -080096 /**
97 * Sets the receiver for {@link CompactRawContactsEditorView} callbacks.
98 */
99 public void setListener(Listener listener) {
100 mListener = listener;
101 }
102
Walter Jangcab3dce2015-02-09 17:48:03 -0800103 @Override
104 protected void onFinishInflate() {
105 super.onFinishInflate();
106
107 mAccountTypeManager = AccountTypeManager.getInstance(getContext());
108 mLayoutInflater = (LayoutInflater)
109 getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
110
Walter Jang3efae4a2015-02-18 11:12:00 -0800111 mHeader = (CompactHeaderView) findViewById(R.id.header);
Walter Jangcab3dce2015-02-09 17:48:03 -0800112 mNames = (LinearLayout) findViewById(R.id.names);
Walter Jangb1c87622015-02-13 17:51:38 -0800113 mPhoneticNames = (LinearLayout) findViewById(R.id.phonetic_names);
114 mNicknames = (LinearLayout) findViewById(R.id.nicknames);
Walter Jangcab3dce2015-02-09 17:48:03 -0800115 mPhoneNumbers = (LinearLayout) findViewById(R.id.phone_numbers);
116 mEmails = (LinearLayout) findViewById(R.id.emails);
117 mOther = (LinearLayout) findViewById(R.id.other);
Walter Jangb6ca2722015-02-20 11:10:25 -0800118 mMoreFields = findViewById(R.id.more_fields);
119 mMoreFields.setOnClickListener(this);
120 }
121
122
123 @Override
124 public void onClick(View view) {
125 if (view.getId() == R.id.more_fields && mListener != null ) {
126 mListener.onExpandEditor();
127 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800128 }
129
130 @Override
131 public void setEnabled(boolean enabled) {
132 super.setEnabled(enabled);
133 setEnabled(enabled, mNames);
Walter Jangb1c87622015-02-13 17:51:38 -0800134 setEnabled(enabled, mPhoneticNames);
135 setEnabled(enabled, mNicknames);
Walter Jangcab3dce2015-02-09 17:48:03 -0800136 setEnabled(enabled, mPhoneNumbers);
137 setEnabled(enabled, mEmails);
138 setEnabled(enabled, mOther);
139 }
140
141 private void setEnabled(boolean enabled, ViewGroup viewGroup) {
142 if (viewGroup != null) {
143 final int childCount = viewGroup.getChildCount();
144 for (int i = 0; i < childCount; i++) {
145 viewGroup.getChildAt(i).setEnabled(enabled);
146 }
147 }
148 }
149
Walter Jang3efae4a2015-02-18 11:12:00 -0800150 /**
151 * Pass through to {@link CompactHeaderView#setPhotoHandler}.
152 */
153 public void setPhotoHandler(PhotoHandler photoHandler) {
154 mHeader.setPhotoHandler(photoHandler);
155 }
156
157 /**
158 * Pass through to {@link CompactHeaderView#setPhoto}.
159 */
160 public void setPhoto(Bitmap bitmap) {
161 mHeader.setPhoto(bitmap);
162 }
163
164 /**
165 * Pass through to {@link CompactHeaderView#isWritablePhotoSet}.
166 */
167 public boolean isWritablePhotoSet() {
168 return mHeader.isWritablePhotoSet();
169 }
170
171 /**
172 * Pass through to {@link CompactHeaderView#getPhotoPopupAnchorView}.
173 */
174 public View getPhotoPopupAnchorView() {
175 return mHeader.getPhotoPopupAnchorView();
176 }
177
178
179 /**
180 * Get the raw contact ID for the CompactHeaderView photo.
181 */
182 // TODO: remove me once we support multiple accounts
183 public long getPhotoRawContactId() {
184 return mPhotoRawContactId;
185 }
186
Walter Jangf46abd82015-02-20 16:52:04 -0800187 public void setState(RawContactDeltaList rawContactDeltas,
188 MaterialColorMapUtils.MaterialPalette materialPalette,
189 ViewIdGenerator viewIdGenerator) {
Walter Jangcab3dce2015-02-09 17:48:03 -0800190 mNames.removeAllViews();
Walter Jangb1c87622015-02-13 17:51:38 -0800191 mPhoneticNames.removeAllViews();
192 mNicknames.removeAllViews();
Walter Jangcab3dce2015-02-09 17:48:03 -0800193 mPhoneNumbers.removeAllViews();
194 mEmails.removeAllViews();
195 mOther.removeAllViews();
196
197 if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
198 return;
199 }
200
201 mViewIdGenerator = viewIdGenerator;
Walter Jangcab3dce2015-02-09 17:48:03 -0800202 setId(mViewIdGenerator.getId(rawContactDeltas.get(0), /* dataKind =*/ null,
203 /* valuesDelta =*/ null, ViewIdGenerator.NO_VIEW_INDEX));
Walter Jangf46abd82015-02-20 16:52:04 -0800204 mMaterialPalette = materialPalette;
Walter Jangcab3dce2015-02-09 17:48:03 -0800205
Walter Jang3efae4a2015-02-18 11:12:00 -0800206 addHeaderView(rawContactDeltas, viewIdGenerator);
Walter Jang10446452015-02-20 13:51:16 -0800207 addStructuredNameView(rawContactDeltas);
Walter Jang3efae4a2015-02-18 11:12:00 -0800208 addEditorViews(rawContactDeltas);
Walter Jange720fde2015-02-17 10:54:14 -0800209 removeExtraEmptyTextFields(mPhoneNumbers);
210 removeExtraEmptyTextFields(mEmails);
Walter Jangcab3dce2015-02-09 17:48:03 -0800211 }
212
Walter Jang3efae4a2015-02-18 11:12:00 -0800213 private void addHeaderView(RawContactDeltaList rawContactDeltas,
Walter Jange720fde2015-02-17 10:54:14 -0800214 ViewIdGenerator viewIdGenerator) {
Walter Jangcab3dce2015-02-09 17:48:03 -0800215 for (RawContactDelta rawContactDelta : rawContactDeltas) {
216 if (!rawContactDelta.isVisible()) {
217 continue;
218 }
219 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
Walter Jange720fde2015-02-17 10:54:14 -0800220
Walter Jang3efae4a2015-02-18 11:12:00 -0800221 // Make sure we have a photo
222 RawContactModifier.ensureKindExists(
223 rawContactDelta, accountType, Photo.CONTENT_ITEM_TYPE);
224
225 final DataKind dataKind = accountType.getKindForMimetype(Photo.CONTENT_ITEM_TYPE);
226 if (dataKind != null) {
Walter Jang10446452015-02-20 13:51:16 -0800227 if (Photo.CONTENT_ITEM_TYPE.equals(dataKind.mimeType)) {
Walter Jang3efae4a2015-02-18 11:12:00 -0800228 mPhotoRawContactId = rawContactDelta.getRawContactId();
229 final ValuesDelta valuesDelta = rawContactDelta.getSuperPrimaryEntry(
Walter Jang10446452015-02-20 13:51:16 -0800230 dataKind.mimeType, /* forceSelection =*/ true);
Walter Jang3efae4a2015-02-18 11:12:00 -0800231 mHeader.setValues(dataKind, valuesDelta, rawContactDelta,
Walter Jangf46abd82015-02-20 16:52:04 -0800232 /* readOnly =*/ !dataKind.editable, mMaterialPalette, viewIdGenerator);
Walter Jang3efae4a2015-02-18 11:12:00 -0800233 return;
234 }
235 }
236 }
237 }
238
Walter Jang10446452015-02-20 13:51:16 -0800239 private void addStructuredNameView(RawContactDeltaList rawContactDeltas) {
240 for (RawContactDelta rawContactDelta : rawContactDeltas) {
241 if (!rawContactDelta.isVisible()) {
242 continue;
243 }
244 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
245
246 // Make sure we have a structured name
247 RawContactModifier.ensureKindExists(
248 rawContactDelta, accountType, StructuredName.CONTENT_ITEM_TYPE);
249
250 final DataKind dataKind = accountType.getKindForMimetype(
251 StructuredName.CONTENT_ITEM_TYPE);
252 if (dataKind != null) {
253 final ValuesDelta valuesDelta = rawContactDelta.getPrimaryEntry(dataKind.mimeType);
254 if (valuesDelta != null) {
255 mNames.addView(inflateStructuredNameEditorView(
256 mNames, accountType, valuesDelta, rawContactDelta));
257 return;
258 }
259 }
260 }
261 }
262
Walter Jang3efae4a2015-02-18 11:12:00 -0800263 private void addEditorViews(RawContactDeltaList rawContactDeltas) {
264 for (RawContactDelta rawContactDelta : rawContactDeltas) {
265 if (!rawContactDelta.isVisible()) {
266 continue;
267 }
268 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
269
Walter Jangcab3dce2015-02-09 17:48:03 -0800270 for (DataKind dataKind : accountType.getSortedDataKinds()) {
271 if (!dataKind.editable) {
272 continue;
273 }
274 final String mimeType = dataKind.mimeType;
275 log(Log.VERBOSE, mimeType + " " + dataKind.fieldList.size() + " field(s)");
276 if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)
Walter Jang10446452015-02-20 13:51:16 -0800277 || StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)
Walter Jangcab3dce2015-02-09 17:48:03 -0800278 || GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jang10446452015-02-20 13:51:16 -0800279 // Photos and name are handled separately; group membership is not supported
Walter Jangcab3dce2015-02-09 17:48:03 -0800280 continue;
Walter Jangcab3dce2015-02-09 17:48:03 -0800281 } else if (DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(mimeType)) {
282 // Use the StructuredName mime type to get values
283 if (hasNonEmptyPrimaryValuesDelta(
284 rawContactDelta, StructuredName.CONTENT_ITEM_TYPE, dataKind)) {
285 final ValuesDelta valuesDelta = rawContactDelta.getPrimaryEntry(
286 StructuredName.CONTENT_ITEM_TYPE);
Walter Jangb1c87622015-02-13 17:51:38 -0800287 mPhoneticNames.addView(inflatePhoneticNameEditorView(
288 mPhoneticNames, accountType, valuesDelta, rawContactDelta));
Walter Jangcab3dce2015-02-09 17:48:03 -0800289 }
290 } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
291 if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
Walter Jangb1c87622015-02-13 17:51:38 -0800292 mNicknames.addView(inflateNicknameEditorView(
293 mNicknames, dataKind, rawContactDelta));
Walter Jangcab3dce2015-02-09 17:48:03 -0800294 }
295 } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jange720fde2015-02-17 10:54:14 -0800296 mPhoneNumbers.addView(inflateKindSectionView(
297 mPhoneNumbers, dataKind, rawContactDelta));
Walter Jangcab3dce2015-02-09 17:48:03 -0800298 } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jange720fde2015-02-17 10:54:14 -0800299 mEmails.addView(inflateKindSectionView(
300 mEmails, dataKind, rawContactDelta));
Walter Jangcab3dce2015-02-09 17:48:03 -0800301 } else if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
302 mOther.addView(inflateKindSectionView(
303 mOther, dataKind, rawContactDelta));
304 }
305 }
306 }
307 }
308
Walter Jange720fde2015-02-17 10:54:14 -0800309 // TODO: avoid inflating extra views and deleting them
310 private void removeExtraEmptyTextFields(ViewGroup viewGroup) {
311 // If there is one (or less) editors, leave it whether it is empty or not
312 if (viewGroup.getChildCount() <= 1) {
Walter Jangb1c87622015-02-13 17:51:38 -0800313 return;
314 }
Walter Jange720fde2015-02-17 10:54:14 -0800315 // Determine if there are any non-empty editors
316 boolean hasAtLeastOneNonEmptyEditorView = false;
317 for (int i = 0; i < viewGroup.getChildCount(); i++) {
318 if (!isEmptyEditorView(viewGroup.getChildAt(i))) {
319 hasAtLeastOneNonEmptyEditorView = true;
Walter Jangb1c87622015-02-13 17:51:38 -0800320 break;
321 }
322 }
Walter Jange720fde2015-02-17 10:54:14 -0800323 if (hasAtLeastOneNonEmptyEditorView) {
324 // There is at least one non-empty editor, remove all the empty ones
325 for (int i = 0; i < viewGroup.getChildCount(); i++) {
326 if (isEmptyEditorView(viewGroup.getChildAt(i))) {
327 viewGroup.getChildAt(i).setVisibility(View.GONE);
Walter Jangb1c87622015-02-13 17:51:38 -0800328 }
329 }
330 } else {
Walter Jange720fde2015-02-17 10:54:14 -0800331 // There is no non-empty editor, keep the first empty view and remove the rest
332 for (int i = 1; i < viewGroup.getChildCount(); i++) {
333 viewGroup.getChildAt(i).setVisibility(View.GONE);
Walter Jangb1c87622015-02-13 17:51:38 -0800334 }
335 }
336 }
337
Walter Jange720fde2015-02-17 10:54:14 -0800338 // TODO: remove this after KindSectionView is rewritten
339 private static boolean isEmptyEditorView(View view) {
340 if (view instanceof TextFieldsEditorView) {
341 final TextFieldsEditorView textFieldsEditorView = (TextFieldsEditorView) view;
342 return textFieldsEditorView.isEmpty();
343 }
344 if (view instanceof KindSectionView) {
345 final KindSectionView kindSectionView = (KindSectionView) view;
346 return kindSectionView.hasEmptyEditor();
347 }
348 return false;
349 }
350
Walter Jangcab3dce2015-02-09 17:48:03 -0800351 private static boolean hasNonEmptyValuesDelta(RawContactDelta rawContactDelta,
352 String mimeType, DataKind dataKind) {
353 return !getNonEmptyValuesDeltas(rawContactDelta, mimeType, dataKind).isEmpty();
354 }
355
356 private static List<ValuesDelta> getNonEmptyValuesDeltas(RawContactDelta rawContactDelta,
357 String mimeType, DataKind dataKind) {
358 final List<ValuesDelta> result = new ArrayList<>();
359 if (rawContactDelta == null) {
360 log(Log.VERBOSE, "Null RawContactDelta");
361 return result;
362 }
363 if (!rawContactDelta.hasMimeEntries(mimeType)) {
364 log(Log.VERBOSE, "No ValueDeltas");
365 return result;
366 }
367 for (ValuesDelta valuesDelta : rawContactDelta.getMimeEntries(mimeType)) {
368 if (valuesDelta == null) {
369 log(Log.VERBOSE, "Null valuesDelta");
370 }
371 for (EditField editField : dataKind.fieldList) {
372 final String column = editField.column;
373 final String value = valuesDelta == null ? null : valuesDelta.getAsString(column);
374 log(Log.VERBOSE, "Field " + column + " empty=" + TextUtils.isEmpty(value) +
375 " value=" + value);
376 if (!TextUtils.isEmpty(value)) {
377 result.add(valuesDelta);
378 }
379 }
380 }
381 return result;
382 }
383
384 private static boolean hasNonEmptyPrimaryValuesDelta(RawContactDelta rawContactDelta,
385 String mimeType, DataKind dataKind) {
386 final ValuesDelta valuesDelta = rawContactDelta.getPrimaryEntry(mimeType);
387 if (valuesDelta == null) {
388 return false;
389 }
390 for (EditField editField : dataKind.fieldList) {
391 final String column = editField.column;
392 final String value = valuesDelta == null ? null : valuesDelta.getAsString(column);
393 log(Log.VERBOSE, "Field (primary) " + column + " empty=" + TextUtils.isEmpty(value) +
394 " value=" + value);
395 if (!TextUtils.isEmpty(value)) {
396 return true;
397 }
398 }
399 return false;
400 }
401
402 private StructuredNameEditorView inflateStructuredNameEditorView(ViewGroup viewGroup,
403 AccountType accountType, ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
404 final StructuredNameEditorView result = (StructuredNameEditorView) mLayoutInflater.inflate(
405 R.layout.structured_name_editor_view, viewGroup, /* attachToRoot =*/ false);
406 result.setValues(
407 accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME),
408 valuesDelta,
409 rawContactDelta,
410 /* readOnly =*/ false,
411 mViewIdGenerator);
412 return result;
413 }
414
415 private PhoneticNameEditorView inflatePhoneticNameEditorView(ViewGroup viewGroup,
416 AccountType accountType, ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
417 final PhoneticNameEditorView result = (PhoneticNameEditorView) mLayoutInflater.inflate(
418 R.layout.phonetic_name_editor_view, viewGroup, /* attachToRoot =*/ false);
419 result.setValues(
420 accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME),
421 valuesDelta,
422 rawContactDelta,
423 /* readOnly =*/ false,
424 mViewIdGenerator);
425 return result;
426 }
427
Walter Jangb1c87622015-02-13 17:51:38 -0800428 private KindSectionView inflateNicknameEditorView(ViewGroup viewGroup, DataKind dataKind,
429 RawContactDelta rawContactDelta) {
430 final KindSectionView result = (KindSectionView) mLayoutInflater.inflate(
431 R.layout.item_kind_section, viewGroup, /* attachToRoot =*/ false);
432 result.setState(
433 dataKind,
Walter Jangcab3dce2015-02-09 17:48:03 -0800434 rawContactDelta,
435 /* readOnly =*/ false,
Walter Jang10446452015-02-20 13:51:16 -0800436 /* showOneEmptyEditor =*/ false,
Walter Jangcab3dce2015-02-09 17:48:03 -0800437 mViewIdGenerator);
438 return result;
439 }
440
441 private KindSectionView inflateKindSectionView(ViewGroup viewGroup, DataKind dataKind,
442 RawContactDelta rawContactDelta) {
443 final KindSectionView result = (KindSectionView) mLayoutInflater.inflate(
444 R.layout.item_kind_section, viewGroup, /* attachToRoot =*/ false);
445 result.setState(
446 dataKind,
447 rawContactDelta,
448 /* readOnly =*/ false,
Walter Jang10446452015-02-20 13:51:16 -0800449 /* showOneEmptyEditor =*/ false,
Walter Jangcab3dce2015-02-09 17:48:03 -0800450 mViewIdGenerator);
451 return result;
452 }
453
454 private static void log(int level, String message) {
455 log(TAG, level, message);
456 }
457
458 private static void log(String tag, int level, String message) {
459 if (Log.isLoggable(tag, level)) {
460 switch (level) {
461 case Log.VERBOSE:
462 Log.v(tag, message);
463 break;
464 case Log.DEBUG:
465 Log.d(tag, message);
466 break;
467 case Log.INFO:
468 Log.i(tag, message);
469 break;
470 case Log.WARN:
471 Log.w(tag, message);
472 break;
473 case Log.ERROR:
474 Log.e(tag, message);
475 break;
476 default:
477 Log.v(tag, message);
478 break;
479 }
480 }
481 }
482}