[Android その４] Androidのアプリケーションの基本開発

# Intentの実装
Intentは、Androidアプリケーション内で操作やデータを他のアプリケーションやアクティビティに送信するためのメカニズムです。Intentを使うことで、異なるコンポーネント(アクティビティ、サービス、ブロードキャストレシーバーなど)の間で情報をやり取りしたり、特定のアクションを開始したりすることができます。

__Intentには大きく2種類あります__ ：
１\. 明示的Intent：
* 特定のアクティビティやコンポーネントを直接呼び出すために使用します。
* 例：現在のアクティビティから別のアクティビティを開始する。

2\. 暗黙的Intent：
* アクションの内容を指定し、それを実行できるコンポーネントをAndroidシステムが選択します。
* 例：写真を撮るアプリや、電話をかけるアプリを起動する。

# メモリアプリへのIntent追加
## 明示的Intent
例えば、メモアプリで新しいメモを追加する際に別のアクティビティを開く場合に、Intentを使用できます。これにより、メインアクティビティから新しいアクティビティへデータを渡すことができます。

__例：メモを追加するための新しいアクティビティを開く__
ここでは、メモを追加するために新しいアクティビティを開く機能を追加します。この新しいアクティビティでユーザーはメモを入力し、その結果がメインアクティビティに返されます。

__1.新しいアクティビティの作成__
```java
package com.example.memoapp;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

public class AddMemoActivity extends AppCompatActivity {

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

        EditText memoInput = findViewById(R.id.memoInput);
        Button saveButton = findViewById(R.id.saveButton);
        Button cancelButton = findViewById(R.id.cancelButton); // キャンセルボタンを取得

        saveButton.setOnClickListener(v -> {
            String memo = memoInput.getText().toString().trim(); // 空白をトリム
            if (memo.isEmpty()) {
                // メモが空白の場合のエラーメッセージを表示
                Toast.makeText(AddMemoActivity.this, "Memo cannot be empty", Toast.LENGTH_SHORT).show();
            } else {
                Intent resultIntent = new Intent();
                resultIntent.putExtra("MEMO_TEXT", memo);
                setResult(RESULT_OK, resultIntent);
                finish(); // 現在のアクティビティを終了して、前のアクティビティに戻る
            }
        });

        // キャンセルボタンのクリックリスナーを設定
        cancelButton.setOnClickListener(v -> finish());
    }
}

```

#### saveButton のクリックリスナー

##### 属性の説明
<details><summary>属性の説明 </summary>

*  'String memo = memoInput.getText().toString().trim();': ユーザーが EditText に入力したテキストを取得し、先頭と末尾の空白を削除します。
*  'if (memo.isEmpty()) { ... } else { ... }':メモが空白かどうかをチェックします。空白の場合は、エラーメッセージを表示し、それ以外の場合はメモを保存します。
*  'Toast.makeText(...).show();':メモが空白の場合に、「Memo cannot be empty」というエラーメッセージを短時間表示します。
*  'Intent resultIntent = new Intent();':結果を呼び出し元のアクティビティに返すための Intent を作成します。
*  'resultIntent.putExtra("MEMO_TEXT", memo);':Intent にメモのテキストを追加します。
*  'setResult(RESULT_OK, resultIntent);':RESULT_OK と resultIntent をセットして、呼び出し元のアクティビティに結果を返します。
*  'finish();':現在のアクティビティを終了し、前のアクティビティに戻ります。
</details>

__2.新しいアクティビティのレイアウトを作成__
<details><summary>レイアウトのコード </summary>

```xml<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AddMemoActivity">

    <!-- メモ入力用のEditText -->
    <EditText
        android:id="@+id/memoInput"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Enter your memo"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        android:layout_margin="16dp" />

    <!-- 保存ボタン -->
    <Button
        android:id="@+id/saveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Save"
        app:layout_constraintTop_toBottomOf="@id/memoInput"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="16dp"/>

    <!-- キャンセルボタン -->
    <Button
        android:id="@+id/cancelButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        app:layout_constraintTop_toBottomOf="@id/saveButton"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

```
</details>

__3.MainActivityの変更__


以下のコードを追加すると、Intentのインスタンスが生成されて、指定されたIntentに遷移されます。

```java
        // メモ追加ボタンのクリックイベント
        Button addButton = findViewById(R.id.addButton);
        addButton.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, AddMemoActivity.class);
            startActivityForResult(intent, 1); // リクエストコードを1に設定
        });
```
__構文__
```java
Intent intent = new Intent(現在のアクティビティ名.this, 遷移先のアクティビティ名.class);
startActivity(intent);
```

## 暗黙的Intent
一方、暗黙的インテント（Implicit Intent） は、特定のアクティビティやサービスを指定する代わりに、特定のアクションやカテゴリ、データタイプを指定することで、Android システムが該当するコンポーネントを選択して起動します。

__暗黙的インテントの例__
```java
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.example.com"));
startActivity(intent);
```
この場合、Intent.ACTION_VIEW アクションと Uri データタイプを指定することで、Android システムがそのアクションを処理できる適切なアクティビティ（通常はブラウザアプリ）を選択します。

__1.MainActivityの修正__

```java
    // メモを共有するメソッド
    private void shareMemo(String memo) {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, memo);
        sendIntent.setType("text/plain");

        Intent shareIntent = Intent.createChooser(sendIntent, null);
        startActivity(shareIntent);
    }
```
* Intent shareIntent = Intent.createChooser(sendIntent, null);
共有アクションを実行できるアプリの一覧をユーザーに表示するための Chooser（選択ダイアログ）を作成します。Intent.createChooser() メソッドは、ユーザーにどのアプリを使ってデータを共有するかを選ばせるための標準ダイアログを提供します。第2引数はダイアログに表示されるタイトルですが、null の場合はシステムが適切なものを自動で設定します。

__2.レイアウトの修正___

```java
   <!-- メモを共有するためのボタン -->
    <Button
        android:id="@+id/shareButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Share Memo"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="16dp"/>
        
```

__MainActivityのonCreateへの追加__
```java
    // 共有ボタンのクリックイベント
    Button shareButton = findViewById(R.id.shareButton);
    shareButton.setOnClickListener(v -> {
        if (!memoList.isEmpty()) {
            shareMemo(memoList.get(memoList.size() - 1));  // 最後のメモを共有
        }
    });
```

## 修正後のコード
いろいろ追加していますが、気になさらず。。。

<details><summary>MainActivity </summary>

```java
package com.example.memoapp;

import android.content.Intent;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> memoList; //メモを格納するリスト
    private ArrayAdapter<String> adapter; //リスト表示用のアダプター

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

        // メモリストの初期化
        memoList = new ArrayList<>();

        // リストビューとアダプターの設定
        ListView listView = findViewById(R.id.listView);
        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, memoList);
        listView.setAdapter(adapter);

        // メモ追加ボタンのクリックイベント
        Button addButton = findViewById(R.id.addButton);
        addButton.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, AddMemoActivity.class);
            startActivityForResult(intent, 1); // リクエストコードを1に設定
        });

        //　メモのクリックイベント(編集)
        listView.setOnItemClickListener(((parent, view, position, id) -> showEditMemoDialog(position)));

        // メモの長押しイベント(削除)
        listView.setOnItemLongClickListener(((parent, view, position, id) -> {
            showDeleteMemoDialog(position);
            return true;
        }));

        // 共有ボタンのクリックイベント
        Button shareButton = findViewById(R.id.shareButton);
        shareButton.setOnClickListener(v -> {
            if (!memoList.isEmpty()) {
                shareMemo(memoList.get(memoList.size() - 1)); // 最後のメモを共有
            }
        });
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1 && resultCode == RESULT_OK) {
            String memo = data.getStringExtra("MEMO_TEXT");
            if (memo != null && !memo.isEmpty()) {
                addMemo(memo);
            }
        }
    }



    private void addMemo(String memo) {
        memoList.add(memo);
        adapter.notifyDataSetChanged(); //リストビュー更新
    }

    private void showEditMemoDialog(int position) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Edit Memo");

        final EditText input = new EditText(this);
        input.setText(memoList.get(position)); // 既存のメモを設定
        builder.setView(input);

        builder.setPositiveButton("Update", (dialog, which) -> {
            String memo = input.getText().toString();
            if (!memo.isEmpty()) {
                updateMemo(position, memo);
            }
        });

        builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
        builder.show();
    }

    // メモの更新
    private void updateMemo(int position,String memo) {
        memoList.set(position,memo); //メモを更新
        adapter.notifyDataSetChanged(); // リストビューを更新
    }

    // メモの削除の確認ダイアログ表示
    private void showDeleteMemoDialog(int position) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Delete Memo");
        builder.setMessage("Are you sure you want to delete this memo?");

        builder.setPositiveButton("Delete", (dialog, which) -> deleteMemo(position));

        builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());

        builder.show();

    }

    // メモの削除
    private void deleteMemo(int position) {
        memoList.remove(position);
        adapter.notifyDataSetChanged();
    }

    // メモを共有するメソッド
    private void shareMemo(String memo) {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, memo);
        sendIntent.setType("text/plain");

        Intent shareIntent = Intent.createChooser(sendIntent, null);
        startActivity(shareIntent);
    }
}
```
</details>



<details><summary>activity_main.xml </summary>

```java

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!-- メモのリストを表示するリストビュー -->
    <ListView
        android:id="@+id/listView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:padding="16dp"
        app:layout_constraintBottom_toTopOf="@+id/addButton"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <!-- メモを追加するためのボタン -->
    <Button
        android:id="@+id/addButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Memo"
        app:layout_constraintBottom_toTopOf="@+id/shareButton"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="16dp"/>

    <!-- メモを共有するためのボタン -->
    <Button
        android:id="@+id/shareButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Share Memo"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

```
</details>

<details><summary>AddMemoActivity </summary>

```java
package com.example.memoapp;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

public class AddMemoActivity extends AppCompatActivity {

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

        EditText memoInput = findViewById(R.id.memoInput);
        Button saveButton = findViewById(R.id.saveButton);
        Button cancelButton = findViewById(R.id.cancelButton); // キャンセルボタンを取得

        saveButton.setOnClickListener(v -> {
            String memo = memoInput.getText().toString().trim(); // 空白をトリム
            if (memo.isEmpty()) {
                // メモが空白の場合のエラーメッセージを表示
                Toast.makeText(AddMemoActivity.this, "Memo cannot be empty", Toast.LENGTH_SHORT).show();
            } else {
                Intent resultIntent = new Intent();
                resultIntent.putExtra("MEMO_TEXT", memo);
                setResult(RESULT_OK, resultIntent);
                finish(); // 現在のアクティビティを終了して、前のアクティビティに戻る
            }
        });

        // キャンセルボタンのクリックリスナーを設定
        cancelButton.setOnClickListener(v -> finish());
    }
}

```

</details>


<details><summary>activity_add_memo.xml </summary>

```java
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AddMemoActivity">

    <!-- メモ入力用のEditText -->
    <EditText
        android:id="@+id/memoInput"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Enter your memo"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        android:layout_margin="16dp" />

    <!-- 保存ボタン -->
    <Button
        android:id="@+id/saveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Save"
        app:layout_constraintTop_toBottomOf="@id/memoInput"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="16dp"/>

    <!-- キャンセルボタン -->
    <Button
        android:id="@+id/cancelButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        app:layout_constraintTop_toBottomOf="@id/saveButton"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="16dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

```

</details>