참고 링크 : 

https://developer.android.com/training/scheduling/alarms.html

http://droidmentor.com/schedule-notifications-using-alarmmanager/

AlarmManager를 이용한 작업 (jobscheduler를 이용한 경우도 같음) 은 기기가 reboot되면 스케쥴해놓은 것이 사라진다. 그러므로 reboot시 재등록을 하는 작업이 필요하다. 

재등록 manifest의 예시

<uses-permission android:name=“android.permission.RECEIVE_BOOT_COMPLETED”/>

<application>
<!– Register the Alarm Receiver –>
<receiver android:name=“.AlarmReceiver”
          android:enabled=“false”>
    <intent-filter>
        <action android:name=“android.intent.action.BOOT_COMPLETED” />
    </intent-filter>
</receiver>
<application>

재등록의 코드 예시 (broadcast receiver에 의해 수행된다. )

public class AlarmReceiver extends BroadcastReceiver {

   String TAG = “AlarmReceiver”;

   @Override
   public void onReceive(Context context, Intent intent) {

                // 이부분에서 alarmmanager 재시작

   }

}

알람생성 예시

Intent intent1 = new Intent(context, cls);
       PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                 DAILY_REMINDER_REQUEST_CODE, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
       AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
       am.cancel(pendingIntent);
       pendingIntent.cancel();

intent의 타깃 class(위의 예시에서는 cls)는 정해진 알람에 따라 수행된다.

알람의 정해진 시기에 따라 수행될 작업은 broadcast receiver에서 수행된다. 

알람 수행 receiver 예시 코드

public class AlarmReceiver extends BroadcastReceiver {

   String TAG = “AlarmReceiver”;

   @Override
   public void onReceive(Context context, Intent intent) {
       //Trigger the notification
        // 이부분에서 notification을 만들고 발생한다.
   }
}

original source : http://www.androiddocs.com/training/wearables/apps/voice.html

사용자로부터 음성으로 data입력을 받으려는 경우

Obtaining Free-form Speech Input

In addition to using voice actions to launch activities, you can also call the system’s built-in Speech Recognizer activity to obtain speech input from users. This is useful to obtain input from users and then process it, such as doing a search or sending it as a message.

In your app, you call

startActivityForResult()

using the

ACTION_RECOGNIZE_SPEECH

action. This starts the speech recognition activity, and you can then handle the result in

onActivityResult()

.

private static final int SPEECH_REQUEST_CODE = 0;

// Create an intent that can start the Speech Recognizer activity
private void displaySpeechRecognizer() {
   Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
   intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
           RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
// Start the activity, the intent will be populated with the speech text
   startActivityForResult(intent, SPEECH_REQUEST_CODE);
}

// This callback is invoked when the Speech Recognizer returns.
// This is where you process the intent and extract the speech text from the intent.
@Override
protected void onActivityResult(int requestCode, int resultCode,
       Intent data) {
   if (requestCode == SPEECH_REQUEST_CODE && resultCode == RESULT_OK) {
       List<String> results = data.getStringArrayListExtra(
               RecognizerIntent.EXTRA_RESULTS);
       String spokenText = results.get(0);
       // Do something with spokenText
   }
   super.onActivityResult(requestCode, resultCode, data);

original source: http://www.androiddocs.com/training/wearables/notifications/pages.html

Adding Pages to a Notification

additional pages appear immediately to the right of the main notification card.

To create a notification with multiple pages:

  1. Create the main notification (the first page) with NotificationCompat.Builder, in the way you’d like the notification to appear on a handset.
  2. Create the additional pages for the wearable with NotificationCompat.Builder.
  3. Apply the pages to the main notification with the addPage() method or add multiple pages in a Collectionwith the addPages() method.

// Create builder for the main notification
NotificationCompat.Builder notificationBuilder =
       new NotificationCompat.Builder(this)
       .setSmallIcon(R.drawable.new_message)
       .setContentTitle("Page 1")
       .setContentText("Short message")
       .setContentIntent(viewPendingIntent);

// Create a big text style for the second page
BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
secondPageStyle.setBigContentTitle("Page 2")
              .bigText("A lot of text...");

// Create second page notification
Notification secondPageNotification =
       new NotificationCompat.Builder(this)
       .setStyle(secondPageStyle)
       .build();

// Extend the notification builder with the second page
Notification notification = notificationBuilder
       .extend(new NotificationCompat.WearableExtender()
               .addPage(secondPageNotification))
       .build();

// Issue the notification
notificationManager =
       NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, notification);

original source :http://www.androiddocs.com/training/wearables/notifications/voice-input.html

Receiving Voice Input in a Notification

If you have handheld notifications that include an action to input text, such as reply to an email, it should normally launch an activity on the handheld device to input the text. However, when your notification appears on a wearable, there is no keyboard input, so you can let users dictate a reply or provide pre-defined text messages using RemoteInput.

When users reply with voice or select one of the available messages, the system attaches the text response to the Intentyou specified for the notification action and sends that intent to your handheld app.

Define the Voice Input

To create an action that supports voice input, create an instance of

RemoteInput.Builder

that you can add to your notification action. This class’s constructor accepts a string that the system uses as the key for the voice input, which you’ll later use to retrieve the text of the input in your handheld app.For example, here’s how to create a

RemoteInput

object that provides a custom label for the voice input prompt:

// Key for the string that's delivered in the action's intent
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";

String replyLabel = getResources().getString(R.string.reply_label);

RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
       .setLabel(replyLabel)
       .build();



Add Pre-defined Text Responses

setChoices()

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string-array name="reply_choices">
       <item>Yes</item>
       <item>No</item>
       <item>Maybe</item>
   </string-array>
</resources>
public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
...
String replyLabel = getResources().getString(R.string.reply_label);
String[] replyChoices = getResources().getStringArray(R.array.reply_choices);

RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
       .setLabel(replyLabel)
       .setChoices(replyChoices)
       .build();



Add the Voice Input as a Notification Action

// Create an intent for the reply action
Intent replyIntent = new Intent(this, ReplyActivity.class);
PendingIntent replyPendingIntent =
       PendingIntent.getActivity(this, 0, replyIntent,
               PendingIntent.FLAG_UPDATE_CURRENT);

// Create the reply action and add the remote input
NotificationCompat.Action action =
       new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
               getString(R.string.label), replyPendingIntent)
               .addRemoteInput(remoteInput)
               .build();

// Build the notification and add the action via WearableExtender
Notification notification =
       new NotificationCompat.Builder(mContext)
               .setSmallIcon(R.drawable.ic_message)
               .setContentTitle(getString(R.string.title))
               .setContentText(getString(R.string.content))
               .extend(new WearableExtender().addAction(action))
               .build();

// Issue the notification
NotificationManagerCompat notificationManager =
       NotificationManagerCompat.from(mContext);
notificationManager.notify(notificationId, notification);

Receiving the Voice Input as a String

(notification은 sync와는 달리 일방통행이라고 하지만 reply action intent를 통해 reply message를 전달 받을수 있다. )

To receive the user’s transcribed message in the activity you declared in the reply action’s intent, call

getResultsFromIntent()

, passing in the “Reply” action’s intent. This method returns a

Bundle

that contains the text response. You can then query the

Bundle

to obtain the response.

Note:

Do not use

Intent.getExtras()

to obtain the voice result, because the voice input is stored as

ClipData

. The

getResultsFromIntent()

method provides a convenient way to receive a character sequence without having to process the

ClipData

yourself.

/**
* Obtain the intent that started this activity by calling
* Activity.getIntent() and pass it into this method to
* get the associated voice input string.
*/

private CharSequence getMessageText(Intent intent) {
   Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
   if (remoteInput != null) {
       return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
   }
   return null;
}

original source : http://www.androiddocs.com/training/wearables/notifications/creating.html

Creating a Notification for Wearables

NotificationCompat.Builder 을 사용하면 기본적으로 mobile, wearable 기기에 전달될 기본 notification을 만들수 있다.



Import the necessary classes

build.gradlefile:

compile "com.android.support:support-v4:20.0.+"
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.NotificationCompat.WearableExtender;



Create Notifications with the Notification Builder

int notificationId = 001;
// Build intent for notification content
Intent viewIntent = new Intent(this, ViewEventActivity.class);
viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
PendingIntent viewPendingIntent =
       PendingIntent.getActivity(this, 0, viewIntent, 0);

NotificationCompat.Builder notificationBuilder =
       new NotificationCompat.Builder(this)
       .setSmallIcon(R.drawable.ic_event)
       .setContentTitle(eventTitle)
       .setContentText(eventLocation)
       .setContentIntent(viewPendingIntent);

// Get an instance of the NotificationManager service
NotificationManagerCompat notificationManager =
       NotificationManagerCompat.from(this);

// Build the notification and issues it with notification manager.
notificationManager.notify(notificationId, notificationBuilder.build());

When this notification appears on a handheld device, the user can invoke the PendingIntent specified by the setContentIntent() method by touching the notification. When this notification appears on an Android wearable, the user can swipe the notification to the left to reveal the Open action, which invokes the intent on the handheld device.

Add Action Buttons

// Build an intent for an action to view a map
Intent mapIntent = new Intent(Intent.ACTION_VIEW);
Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
mapIntent.setData(geoUri);
PendingIntent mapPendingIntent =
       PendingIntent.getActivity(this, 0, mapIntent, 0);

NotificationCompat.Builder notificationBuilder =
       new NotificationCompat.Builder(this)
       .setSmallIcon(R.drawable.ic_event)
       .setContentTitle(eventTitle)
       .setContentText(eventLocation)
       .setContentIntent(viewPendingIntent)
       .addAction(R.drawable.ic_map,
               getString(R.string.map), mapPendingIntent);

On a handheld, the action appears as an additional button attached to the notification. On a wearable, the action appears as a large button when the user swipes the notification to the left. When the user taps the action, the associated intent is invoked on the handheld.

Specify Wearable-only Actions

If you want the actions available on the wearable to be different from those on the handheld, then use WearableExtender.addAction(). Once you add an action with this method, the wearable does not display any other actions added with NotificationCompat.Builder.addAction(). That is, only the actions added with WearableExtender.addAction() appear on the wearable and they do not appear on the handheld.

// Create an intent for the reply action
Intent actionIntent = new Intent(this, ActionActivity.class);
PendingIntent actionPendingIntent =
       PendingIntent.getActivity(this, 0, actionIntent,
               PendingIntent.FLAG_UPDATE_CURRENT);

// Create the action
NotificationCompat.Action action =
       new NotificationCompat.Action.Builder(R.drawable.ic_action,
               getString(R.string.label), actionPendingIntent)
               .build();

// Build the notification and add the action via WearableExtender
Notification notification =
       new NotificationCompat.Builder(mContext)
               .setSmallIcon(R.drawable.ic_message)
               .setContentTitle(getString(R.string.title))
               .setContentText(getString(R.string.content))
               .extend(new WearableExtender().addAction(action))
               .build();



Add a Big View

To add the extended content to your notification, call setStyle() on the NotificationCompat.Builder object, passing it an instance of eitherBigTextStyle or InboxStyle.

// Specify the 'big view' content to display the long
// event description that may not fit the normal content text.
BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
bigStyle.bigText(eventDescription);

NotificationCompat.Builder notificationBuilder =
       new NotificationCompat.Builder(this)
       .setSmallIcon(R.drawable.ic_event)
       .setLargeIcon(BitmapFactory.decodeResource(
               getResources(), R.drawable.notif_background))
       .setContentTitle(eventTitle)
       .setContentText(eventLocation)
       .setContentIntent(viewPendingIntent)
       .addAction(R.drawable.ic_map,
               getString(R.string.map), mapPendingIntent)
       .setStyle(bigStyle);



Add Wearable Features For a Notification

예시) 

setHintHideIcon(), setBackground()

  1. Create an instance of a WearableExtender, setting the wearable-specific options for the notication.
  2. Create an instance of NotificationCompat.Builder, setting the desired properties for your notification as described earlier in this lesson.
  3. Call extend() on the notification and pass in the WearableExtender. This applies the wearable options to the notification.
  4. Call build() to build the notification.
// Create a WearableExtender to add functionality for wearables
NotificationCompat.WearableExtender wearableExtender =
       new NotificationCompat.WearableExtender()
       .setHintHideIcon(true)
       .setBackground(mBitmap);

// Create a NotificationCompat.Builder to build a standard notification
// then extend it with the WearableExtender
Notification notif = new NotificationCompat.Builder(mContext)
       .setContentTitle("New mail from " + sender)
       .setContentText(subject)
       .setSmallIcon(R.drawable.new_mail)
       .extend(wearableExtender)
       .build();

Note: The bitmap that you use with setBackground() should have a resolution of 400×400 for non-scrolling backgrounds and 640×400 for backgrounds that support parallax scrolling. Place these bitmap images in the res/drawable-nodpi directory. Place other non-bitmap resources for wearable notifications, such as those used with the setContentIcon() method, in the res/drawable-hdpi directory.

If you ever need to read wearable-specific options at a later time, use the corresponding get method for the option. This example calls the getHintHideIcon()

NotificationCompat.WearableExtender wearableExtender =
       new NotificationCompat.WearableExtender(notif);
boolean hintHideIcon = wearableExtender.getHintHideIcon();



Deliver the Notification

When you want to deliver your notifications, always use the NotificationManagerCompat API instead ofNotificationManager:

// Get an instance of the NotificationManager service
NotificationManagerCompat notificationManager =
       NotificationManagerCompat.from(mContext);

// Issue the notification with notification manager.
notificationManager.notify(notificationId, notif);

original source: http://www.androiddocs.com/training/wearables/notifications/pages.html

Adding Pages to a Notification

When you’d like to provide more information without requiring users to open your app on their handheld device, you can add one or more pages to the notification on the wearable. (notification에 추가적으로 정보를 전달하고 싶은 경우 pages를 이용한다.)

  1. Create the main notification (the first page) with NotificationCompat.Builder, in the way you’d like the notification to appear on a handset.
  2. Create the additional pages for the wearable with NotificationCompat.Builder.
  3. Apply the pages to the main notification with the addPage() method or add multiple pages in a Collectionwith the addPages() method.
// Create builder for the main notification
NotificationCompat.Builder notificationBuilder =
       new NotificationCompat.Builder(this)
       .setSmallIcon(R.drawable.new_message)
       .setContentTitle("Page 1")
       .setContentText("Short message")
       .setContentIntent(viewPendingIntent);

// Create a big text style for the second page
BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
secondPageStyle.setBigContentTitle("Page 2")
              .bigText("A lot of text...");

// Create second page notification
Notification secondPageNotification =
       new NotificationCompat.Builder(this)
       .setStyle(secondPageStyle)
       .build();

// Extend the notification builder with the second page
Notification notification = notificationBuilder
       .extend(new NotificationCompat.WearableExtender()
               .addPage(secondPageNotification))
       .build();

// Issue the notification
notificationManager =
       NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, notification);

original source:  https://developer.android.com/training/wearables/apps/layouts.html

Create Custom Notifications

ou should create notifications on the phone and let them automatically sync to the wearable.

Note: When creating custom notifications on the watch, you can use the standard notification APIs (API Level 20) instead of the Support Library.

1.Create a layout and set it as the content view for the activity that you want to display.

public void onCreate(Bundle bundle){
   ...
   setContentView(R.layout.notification_activity);
}

 2.in the Android manifest 

For example:

<activity android:name="com.example.MyDisplayActivity"
   android:exported="true"
   android:allowEmbedded="true"
   android:taskAffinity=""
   android:theme="@android:style/Theme.DeviceDefault.Light" />

3.Create a PendingIntent for the activity that you want to display. 

Intent notificationIntent = new Intent(this, NotificationActivity.class);
PendingIntent notificationPendingIntent = PendingIntent.getActivity(
       this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

4.Build a Notification and call setDisplayIntent() providing the PendingIntent. The system uses this PendingIntent to launch the activity when users view your notification.

5.Issue the notification using the notify() method.

Create Layouts with the Wear UI Library

사용자 정의 layout을 만드는데 유용한 wear 에 특화된 ui library element

  • BoxInsetLayout  A FrameLayout object that’s aware of screen shape and can box its children in the center square of a round screen.
  • ConfirmationActivity  An activity that displays confirmation animations after the user completes an action.
  • AnimationSet  A group of animations that should be played together.
  • CircularProgressLayout  A layout that provides a circular countdown timer around a child view. Typically used as an automatic timer to confirm an operation after a short delay has elapsed.
  • PagerSnapHelper  Implementation of the SnapHelper instance supporting pager style snapping in either vertical or horizontal orientation.
  • ProgressBar  Displays a bar to the user representing how far the operation has progressed; the application can change the amount of progress (modifying the length of the bar) as it moves forward.