woshidan's blog

あいとゆうきとITと、とっておきの話。

mixi Android training 第四回分についてメモ2

http://mixi-inc.github.io/AndroidTraining/fundamentals/2.04.messaging-and-notification.html

の続きです。

課題

AndroidStudio/assignments/fundamentals/4th/MessagingAndNotification/build.gradleを開き、 以下の問題に取り組んでください。

Intent

その1

画面にボタンが 1 つ配置されています。このボタンのクリックイベントを拾う処理の中で、ブラウザを立ち上げ、指定した URL を読み込むためのIntentオブジェクトを作成し、ブラウザを立ち上げるところまでを実装してください。

BroadcastでIntentを送る。IntentのアクションはViewでURIを渡す? みたいなところまで考えました。

  Intent intent = new Intent();
  intent.setAction(Intent.ACTION_VIEW);
  intent.setData("http://mixi.jp");
  sendBroadcast(intent);

とりあえず、第一案はこれでいったところ、

Error:(25, 28) エラー: 不適合な型: StringをUriに変換できません:

と表示されて、解答を見た結果、

Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("http://mixi.jp"));
                startActivity(intent);

Uri.parseが必要であり、また、startActivity()を使うのでした。 sendBroadcastでブラウザに対してIntentを送るのか、と思っていました。

その2

画面にボタンが 1 つ配置されています。このボタンのクリックイベントを拾う処理の中で、EditText を 1 つと、ボタンを 1 つ配置した新しい Activity を立ち上げ、EditText の入力内容を結果として返し、返された結果を Toast で表示するようにしてください。

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // TODO EditText と ボタンを 1 つずつ持つ新しい Activity を呼び出し、ボタンを押した時に結果を返すように実装する
        // TODO 返ってきた結果を Toast で表示するところも実装すること
    }
});

これは、プロジェクト内を見るとEditActivityを呼び出すっぽい。呼び出し先のアクティビティから結果を受け取りたい時は、Intentの送信をstartActivityForResultで行えばよいから、まず、

startActivityForResult(new Intent(IntentActivity2.this, EditActivity.class), EditActivity.REQUEST_CODE_EDIT);

で、次の受信側で、Intentの識別するint型の定数(EditActivity.REQUEST_CODE_EDIT)を定義して、

public static int REQUEST_CODE_EDIT = 30;
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // TODO ここで、id が MyEdit の EditText からテキストを取得して、結果にセットする
    }
});

EditTextからテキストを取得するには、

editText.getText()

のようにすればよいみたいです。で、呼び出された側から結果を返す時は、setResult(int, Intent)finish()を使えば良いので。

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // TODO ここで、id が MyEdit の EditText からテキストを取得して、結果にセットする
         Editable text = ((EditText)findViewById(R.id.MyEdit)).getText();
         Intent intent = new Intent();
         intent.putExtra("text", text.toString());
         setResult(RESULT_OK, intent);
         finish();
    }
});

最後に、呼び出し側のActivityに呼び出された側から返ってきた結果を受け取るonActivityResult(int requestCode, int resultCode, Intent data)を追加します。

内容は、requestCodeがREQUEST_CODE_EDITだったら、受け取ったintentの中のtextをToastで表示する、というものです。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Fragmentのときは本当に困るっぽいおまじない
        super.onActivityResult(requestCode, resultCode, data);

        switch(requestCode) {
            case EditActivity.REQUEST_CODE_EDIT:
                // この部分は、これで書いたら「定数式が必要です」と怒られてしまったので、
                // とりあえず最終的に生のint定数を書いてしまった...
                Toast.makeText(this, data.getStringExtra("text"), 50).show();
                return;
            default:
                return;
        }
    };

Notification

その1

アイコン、タイトル、詳細メッセージを含む通知を表示してください。通知を表示するときに、バイブレーションを作動させるようにしてください。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification1);

        // TODO ここで通知を表示する
        // Intentを作成
        Intent intent = new Intent(this, MainActivity.class);
        // PendingIntentにIntentを入れる
        PendingIntent activityIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // PendingIntentを持ったNotificationを作成
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        Notification notification = builder.setWhen(SystemClock.currentThreadTimeMillis())
                                           .setContentTitle("NotificationActivity1")
                                           .setSmallIcon(R.drawable.ic_launcher)
                                           .setContentText("通知の詳しい内容をここに書きます。")
                                           .setContentIntent(activityIntent)
                                           .setAutoCancel(true) // タップすれば消える設定
                                           .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS) // バイブ等の設定
                                           .build();
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notification);
    }
その2

アイコン、タイトル、詳細メッセージと、通知を表示した時に展開するティッカーテキストを含む通知を表示してください( Activity は課題 1 と同じもので良い)。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification1);

        // TODO ここで通知を表示する
        // Intentを作成
        Intent intent = new Intent(this, MainActivity.class);
        // PendingIntentにIntentを入れる
        PendingIntent activityIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // PendingIntentを持ったNotificationを作成
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        Notification notification = builder.setWhen(SystemClock.currentThreadTimeMillis())
                                           .setContentTitle("NotificationActivity1")
                                           .setSmallIcon(R.drawable.ic_launcher)
                                           .setContentText("通知の詳しい内容をここに書きます。")
                                           .setContentIntent(activityIntent)
                                           .setAutoCancel(true) // タップすれば消える設定
                                           .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS) // バイブ等の設定
                                           .setTicker("通知ダヨ!")// ティッカーテキスト
                                           .build();
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notification);
    }
その3

アイコン、タイトル、詳細メッセージを含む通知を表示してください。通知をタップしたら、指定した ACTION を受け取ることが出来る Activity を実行するようにしてください。

これは、Intentが明示Intentでなくて暗黙的Intentの場合だと思います。

疲れたので、解答を引用させていただいて、確認して終わります。。

@Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_notification2);

      Intent intent = new Intent(); // Broadcastするときは、元のIntentなどの情報は要らない
      intent.setAction(ACTION_VIEW_MY_OWN);  // マニフェストの中のActivityのいくつかのintent-filterに<action android:name="jp.mixi.assignment.messagingandnotification.android.intent.action.VIEW_MY_OWN" />があるintent filterを書いておく事!
      PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

      NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
      Notification notification = builder
              .setSmallIcon(R.drawable.ic_launcher)
              .setContentTitle("通知テスト")
              .setContentText("通知の詳細テスト")
              .setContentIntent(pendingIntent)
              .build();

      NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      manager.notify(0, notification); // この辺は明示的Intentの場合と差がない
  }

見てて分かっているつもりでも、実際疲れました。 次回からなんと実践編なのですね。いやはや。