新卒入社半年でRakumonの開発でしてきたこと

# Rakumonについて
* **いつでもどこでもRakumonを使える**
  Rakumonは**24時間365日**、**家** でも **外出先** でも **通学中** でも利用することができます。

* **厳選されたRakumon講師陣**
  Rakumonで採用している講師陣は、**国公立などの難関大学**に在籍している学生を採用しています。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477151/3e2e2550-0dec-cae9-9d1c-ac4c096d8a22.png" /> 
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477151/68ea9bea-9834-e4cb-60a8-99c50f7c4620.png" />

* **豊富な質問対応教科**
質問できる教科は以下の表通りになっています。

| 教科 | 小学生 |中学生 | 高校生 |
|:-:|:-:|:-:|:-:|
| 国語  | ⭕️  | ⭕️  | ⭕️  |
| 数学(算数)  | ⭕️  | ⭕️  | ⭕️  |
| 社会  | ⭕️  |⭕️ | -  |
| 理科  | ⭕️  | ⭕️  | -  |
| 英語  | -  | ⭕️  | ⭕️  |
| 実技 | -  | ⭕️  | -  |
| 物理  | -  | -  | ⭕️  |
| 化学  | -  | -  | ⭕️  |
| 地学  | -  | -  | ⭕️  |
| 生物  | -  | -  | ⭕️  |
| 地理  | -  | -  | ⭕️  |
| 世界史  | -  | -  | ⭕️  |
| 日本史  | -  | -  | ⭕️  |
| 現代社会  | -  | -  | ⭕️  |
| 政治経済  | -  | -  | ⭕️  |
| 倫理  | -  | -  | ⭕️  |

さらに、勉強法やプログラミングの質問をすることが可能です。

https://play.google.com/store/apps/details?id=com.rakumon.student

https://apps.apple.com/jp/app/id1563619844

そのプロジェクトに配属されてからやってきた開発について一部紹介していきます。

# URLのリンク化
私の人生の中で一番最初にやった開発です。
Rakumonのチャット画面で、チャットの文章にURLを送信するとリンク化して、タップするとそのサイトに遷移する機能です。
一番簡単に実装する方法としては、XMLファイルに `android:autoLink="all"` をつけるのが一番手っ取り早いやり方です。
ただこの方法だと、リンク化されなくても良い文までリンク化されてしまうので、チャットシステムの機能として採用するには使い勝手が悪いです。
なので、正確にURLの文だけをリンク化する機能を実装するには、独自で実装する必要があります。
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477151/f34a6ea9-2114-67c7-237b-e2a04b01c71f.png" /> <img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477151/e30a0b68-0f88-840b-767f-e7e901d53d90.png" />
　　　　独自実装　　　　　　　                 　autolink属性
</br>
</br>

```Chat.kt
// チャット中のURLのリンク化をする
val text = viewHolder.txtViewLeft.text
// SpannableStringBuilderでURL装飾を行う
val spannableString = SpannableStringBuilder(text)
// 入力されたテキストがURLかどうか判断する
val matcher = 
    Pattern.compile("(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]")
        .matcher(text)
            while (matcher.find()) {
                val url = matcher.group()
                val start = matcher.start()
                val end = matcher.end()

                // URLをタップした時の画面遷移処理
                spannableString.setSpan(UrlClickableAdapter(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
                // URL文の色調整
                spannableString.setSpan(ForegroundColorSpan(Color.rgb(0,120,255)), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            // リンク化されたURL文の表示
            viewHolder.txtViewLeft.text = spannableString
            viewHolder.txtViewLeft.movementMethod = LinkMovementMethod.getInstance()
```

コードに関してはほぼこのサイトを参照しました。

https://android.gcreate.jp/482/

URLの遷移処理は別のAdapterファイルに記述しています。

```UrlClickableAdapter.kt
class UrlClickableAdapter(private val url: String): ClickableSpan(){

    // 重複タップ防止フラグ
    var clickable = true

    override fun onClick(widget: View) {
        if(clickable) {
            clickable = false
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
            widget.context.startActivity(intent)

            // 2秒間urlクリック遷移を停止
            val runnable = Runnable {
                clickable = true
            }

            android.os.Handler(Looper.getMainLooper()).postDelayed(runnable, 2000)
        }
    }
}
```

さらにWebサイトの二重起動を防ぐための機能も実装しています。

# 質問文テンプレート機能

この機能は、質問文テンプレート画面で、使用するボタンをタップすると前画面の質問文を入力するテキストにテンプレート文が貼り付けられる機能です。

```questionTemplate.kt
class QuestionTemplateActivity : BaseActivity() {
    private lateinit var binding: ActivityQuestiontemplateBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityQuestiontemplateBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // タイトルバー設定
        binding.navigationBar.title = getString(R.string.question_template_VC_title)
        binding.navigationBar.left = ContextCompat.getDrawable(this, R.drawable.navibar_back_green)
        binding.navigationBar.setLeftClickListener {
            this.onBackPressed()
        }

        // テンプレート文設定
        binding.txtViewTemplate.text = getString(R.string.question_template1)
        binding.txtViewTemplate.movementMethod = ScrollingMovementMethod.getInstance()

        // 使用ボタン設定
        binding.btnUseTemplate.setOnClickListener {
            val text = binding.txtViewTemplate.text.toString()
            // テンプレート文の受け渡し設定
            intent.putExtra("text", text)
            setResult(Activity.RESULT_OK, intent)

            finish()
        }
    }
}
```
画面遷移をするだけならstartActivityを使用しますが,
遷移先の画面の結果を受け取りたい時は、startActivityForResultメソッドを使います。
```questonContent.kt
// 質問文テンプレートボタン
        binding.btnQuestionTemplate.setOnClickListener {
            val intent = Intent(this, QuestionTemplateActivity::class.java)
            val requestCode = 910
            startActivityForResult(intent, requestCode)
        }
```
startActivityForResultメソッドの引数にrequestCodeがあり、それを使ってどのActivityからの結果なのかを判断しています。
ただ、startActivityForResultメソッドを使うことは現在非推奨になってます。
代わりに、ActivityResultAPIを使用することを推奨しているみたいです。

# 最後に
この記事で紹介した機能以外にもRakumonは様々な機能を実装していますので、気になる方はぜひインストールしてみてください。

https://play.google.com/store/apps/details?id=com.rakumon.student

https://apps.apple.com/jp/app/id1563619844