Home | History | Annotate | Download | only in com.example.android.lnotifications
      1 /*
      2 * Copyright 2014 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 
     17 package com.example.android.lnotifications;
     18 
     19 import android.app.Activity;
     20 import android.app.Fragment;
     21 import android.app.Notification;
     22 import android.app.NotificationManager;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.database.Cursor;
     26 import android.graphics.Bitmap;
     27 import android.graphics.drawable.BitmapDrawable;
     28 import android.graphics.drawable.Drawable;
     29 import android.net.Uri;
     30 import android.os.Bundle;
     31 import android.provider.ContactsContract;
     32 import android.provider.MediaStore;
     33 import android.util.Log;
     34 import android.view.LayoutInflater;
     35 import android.view.View;
     36 import android.view.ViewGroup;
     37 import android.widget.ArrayAdapter;
     38 import android.widget.Button;
     39 import android.widget.ImageView;
     40 import android.widget.Spinner;
     41 import android.widget.TextView;
     42 import android.widget.Toast;
     43 
     44 import java.io.IOException;
     45 import java.util.Random;
     46 
     47 /**
     48  * Fragment that demonstrates how to attach metadata introduced in Android L, such as
     49  * priority data, notification category and person data.
     50  */
     51 public class OtherMetadataFragment extends Fragment {
     52 
     53     private static final String TAG = OtherMetadataFragment.class.getSimpleName();
     54 
     55     /**
     56      * Request code used for picking a contact.
     57      */
     58     public static final int REQUEST_CODE_PICK_CONTACT = 1;
     59 
     60     /**
     61      * Incremental Integer used for ID for notifications so that each notification will be
     62      * treated differently.
     63      */
     64     private Integer mIncrementalNotificationId = Integer.valueOf(0);
     65 
     66     private NotificationManager mNotificationManager;
     67 
     68     /**
     69      * Button to show a notification.
     70      */
     71     private Button mShowNotificationButton;
     72 
     73     /**
     74      *  Spinner that holds possible categories used for a notification as
     75      *  {@link Notification.Builder#setCategory(String)}.
     76      */
     77     private Spinner mCategorySpinner;
     78 
     79     /**
     80      * Spinner that holds possible priorities used for a notification as
     81      * {@link Notification.Builder#setPriority(int)}.
     82      */
     83     private Spinner mPrioritySpinner;
     84 
     85     /**
     86      * Holds a URI for the person to be attached to the notification.
     87      */
     88     //@VisibleForTesting
     89     Uri mContactUri;
     90 
     91     /**
     92      * Use this factory method to create a new instance of
     93      * this fragment using the provided parameters.
     94      *
     95      * @return A new instance of fragment NotificationFragment.
     96      */
     97     public static OtherMetadataFragment newInstance() {
     98         OtherMetadataFragment fragment = new OtherMetadataFragment();
     99         fragment.setRetainInstance(true);
    100         return fragment;
    101     }
    102 
    103     public OtherMetadataFragment() {
    104         // Required empty public constructor
    105     }
    106 
    107     @Override
    108     public void onCreate(Bundle savedInstanceState) {
    109         super.onCreate(savedInstanceState);
    110         mNotificationManager = (NotificationManager) getActivity().getSystemService(Context
    111                 .NOTIFICATION_SERVICE);
    112     }
    113 
    114     @Override
    115     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    116                              Bundle savedInstanceState) {
    117         // Inflate the layout for this fragment
    118         return inflater.inflate(R.layout.fragment_other_metadata, container, false);
    119     }
    120 
    121     @Override
    122     public void onViewCreated(View view, Bundle savedInstanceState) {
    123         super.onViewCreated(view, savedInstanceState);
    124         mShowNotificationButton = (Button) view.findViewById(R.id.show_notification_button);
    125         mShowNotificationButton.setOnClickListener(new View.OnClickListener() {
    126             @Override
    127             public void onClick(View view) {
    128                 Priority selectedPriority = (Priority) mPrioritySpinner.getSelectedItem();
    129                 Category selectedCategory = (Category) mCategorySpinner.getSelectedItem();
    130                 showNotificationClicked(selectedPriority, selectedCategory, mContactUri);
    131             }
    132         });
    133 
    134         mCategorySpinner = (Spinner) view.findViewById(R.id.category_spinner);
    135         ArrayAdapter<Category> categoryArrayAdapter = new ArrayAdapter<Category>(getActivity(),
    136                 android.R.layout.simple_spinner_item, Category.values());
    137         categoryArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    138         mCategorySpinner.setAdapter(categoryArrayAdapter);
    139 
    140         mPrioritySpinner = (Spinner) view.findViewById(R.id.priority_spinner);
    141         ArrayAdapter<Priority> priorityArrayAdapter = new ArrayAdapter<Priority>(getActivity(),
    142                 android.R.layout.simple_spinner_item, Priority.values());
    143         priorityArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    144         mPrioritySpinner.setAdapter(priorityArrayAdapter);
    145 
    146         view.findViewById(R.id.attach_person).setOnClickListener(new View.OnClickListener() {
    147             @Override
    148             public void onClick(View view) {
    149                 findContact();
    150             }
    151         });
    152 
    153         view.findViewById(R.id.contact_entry).setVisibility(View.GONE);
    154     }
    155 
    156     @Override
    157     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    158         super.onActivityResult(requestCode, resultCode, data);
    159         switch (requestCode) {
    160             case REQUEST_CODE_PICK_CONTACT:
    161                 if (resultCode == Activity.RESULT_OK) {
    162                     Uri contactUri = data.getData();
    163                     mContactUri = contactUri;
    164                     updateContactEntryFromUri(contactUri);
    165                 }
    166                 break;
    167         }
    168     }
    169 
    170     /**
    171      * Invoked when {@link #mShowNotificationButton} is clicked.
    172      * Creates a new notification and sets metadata passed as arguments.
    173      *
    174      * @param priority   The priority metadata.
    175      * @param category   The category metadata.
    176      * @param contactUri The URI to be added to the new notification as metadata.
    177      *
    178      * @return A Notification instance.
    179      */
    180     //@VisibleForTesting
    181     Notification createNotification(Priority priority, Category category, Uri contactUri) {
    182         Notification.Builder notificationBuilder = new Notification.Builder(getActivity())
    183                 .setContentTitle("Notification with other metadata")
    184                 .setSmallIcon(R.drawable.ic_launcher_notification)
    185                 .setPriority(priority.value)
    186                 .setCategory(category.value)
    187                 .setContentText(String.format("Category %s, Priority %s", category.value,
    188                         priority.name()));
    189         if (contactUri != null) {
    190             notificationBuilder.addPerson(contactUri.toString());
    191             Bitmap photoBitmap = loadBitmapFromContactUri(contactUri);
    192             if (photoBitmap != null) {
    193                 notificationBuilder.setLargeIcon(photoBitmap);
    194             }
    195         }
    196         return notificationBuilder.build();
    197     }
    198 
    199     /**
    200      * Invoked when {@link #mShowNotificationButton} is clicked.
    201      * Creates a new notification and sets metadata passed as arguments.
    202      *
    203      * @param priority   The priority metadata.
    204      * @param category   The category metadata.
    205      * @param contactUri The URI to be added to the new notification as metadata.
    206      */
    207     private void showNotificationClicked(Priority priority, Category category, Uri contactUri) {
    208         // Assigns a unique (incremented) notification ID in order to treat each notification as a
    209         // different one. This helps demonstrate how a priority flag affects ordering.
    210         mIncrementalNotificationId = new Integer(mIncrementalNotificationId + 1);
    211         mNotificationManager.notify(mIncrementalNotificationId, createNotification(priority,
    212                 category, contactUri));
    213         Toast.makeText(getActivity(), "Show Notification clicked", Toast.LENGTH_SHORT).show();
    214     }
    215 
    216     private void findContact() {
    217         Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
    218         startActivityForResult(intent, REQUEST_CODE_PICK_CONTACT);
    219     }
    220 
    221     /**
    222      * Returns a {@link Bitmap} from the Uri specified as the argument.
    223      *
    224      * @param contactUri The Uri from which the result Bitmap is created.
    225      * @return The {@link Bitmap} instance retrieved from the contactUri.
    226      */
    227     private Bitmap loadBitmapFromContactUri(Uri contactUri) {
    228         if (contactUri == null) {
    229             return null;
    230         }
    231         Bitmap result = null;
    232         Cursor cursor = getActivity().getContentResolver().query(contactUri, null, null, null,
    233                 null);
    234         if (cursor != null && cursor.moveToFirst()) {
    235             int idx = cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID);
    236             String hasPhoto = cursor.getString(idx);
    237             Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo
    238                     .CONTENT_DIRECTORY);
    239             if (hasPhoto != null) {
    240                 try {
    241                     result = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver()
    242                             , photoUri);
    243                 } catch (IOException e) {
    244                     Log.e(TAG, String.format("Failed to load resource. Uri %s", photoUri), e);
    245                 }
    246             } else {
    247                 Drawable defaultContactDrawable = getActivity().getResources().getDrawable(R
    248                         .drawable.ic_contact_picture);
    249                 result = ((BitmapDrawable) defaultContactDrawable).getBitmap();
    250             }
    251         }
    252         return result;
    253     }
    254 
    255     /**
    256      * Updates the Contact information on the screen when a contact is picked.
    257      *
    258      * @param contactUri The Uri from which the contact is retrieved.
    259      */
    260     private void updateContactEntryFromUri(Uri contactUri) {
    261         Cursor cursor = getActivity().getContentResolver().query(contactUri, null, null, null,
    262                 null);
    263         if (cursor != null && cursor.moveToFirst()) {
    264             int idx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
    265             String name = cursor.getString(idx);
    266             idx = cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID);
    267             String hasPhoto = cursor.getString(idx);
    268 
    269             Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo
    270                     .CONTENT_DIRECTORY);
    271             ImageView contactPhoto = (ImageView) getActivity().findViewById(R.id.contact_photo);
    272             if (hasPhoto != null) {
    273                 contactPhoto.setImageURI(photoUri);
    274             } else {
    275                 Drawable defaultContactDrawable = getActivity().getResources().getDrawable(R
    276                         .drawable.ic_contact_picture);
    277                 contactPhoto.setImageDrawable(defaultContactDrawable);
    278             }
    279             TextView contactName = (TextView) getActivity().findViewById(R.id.contact_name);
    280             contactName.setText(name);
    281 
    282             getActivity().findViewById(R.id.contact_entry).setVisibility(View.VISIBLE);
    283             getActivity().findViewById(R.id.attach_person).setVisibility(View.GONE);
    284             getActivity().findViewById(R.id.click_to_change).setOnClickListener(new View.OnClickListener() {
    285                 @Override
    286                 public void onClick(View view) {
    287                     findContact();
    288                 }
    289             });
    290             Log.i(TAG, String.format("Contact updated. Name %s, PhotoUri %s", name, photoUri));
    291         }
    292     }
    293 
    294     /**
    295      * Enum indicating possible categories in {@link Notification} used from
    296      * {@link #mCategorySpinner}.
    297      */
    298     //@VisibleForTesting
    299     static enum Category {
    300         ALARM("alarm"),
    301         CALL("call"),
    302         EMAIL("email"),
    303         ERROR("err"),
    304         EVENT("event"),
    305         MESSAGE("msg"),
    306         PROGRESS("progress"),
    307         PROMO("promo"),
    308         RECOMMENDATION("recommendation"),
    309         SERVICE("service"),
    310         SOCIAL("social"),
    311         STATUS("status"),
    312         SYSTEM("sys"),
    313         TRANSPORT("transport");
    314 
    315         private final String value;
    316 
    317         Category(String value) {
    318             this.value = value;
    319         }
    320 
    321         @Override
    322         public String toString() {
    323             return value;
    324         }
    325     }
    326 
    327     /**
    328      * Enum indicating possible priorities in {@link Notification} used from
    329      * {@link #mPrioritySpinner}.
    330      */
    331     //@VisibleForTesting
    332     static enum Priority {
    333         DEFAULT(Notification.PRIORITY_DEFAULT),
    334         MAX(Notification.PRIORITY_MAX),
    335         HIGH(Notification.PRIORITY_HIGH),
    336         LOW(Notification.PRIORITY_LOW),
    337         MIN(Notification.PRIORITY_MIN);
    338 
    339         private final int value;
    340 
    341         Priority(int value) {
    342             this.value = value;
    343         }
    344     }
    345 }
    346