Chapter 9 Multimedia

  1. notice

    1. basis

      Android 8.0 introduced the concept of notification channels, and each notification must belong to a corresponding channel. Such as private messages, news, likes and so on

      // Create channel
      val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          notificationManager.createNotificationChannel(
            	// Channel ID, channel name (shown to the user, Settings and long press notification can be seen), notification importance level
              NotificationChannel(
                  "like"."Thumb up", NotificationManager.IMPORTANCE_DEFAULT
              )
          )
      }
      Copy the code

      Create a notification:

      // Use NotificationCompat to ensure that all Android versions behave the same. "like" is the notification channel
      val build = NotificationCompat.Builder(this."like")
          .setContentTitle("This is content title")
          .setContentText("This is content text")
          .setSmallIcon(R.drawable.apple_pic)
          .setLargeIcon(
              BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_foreground)
          )
          .build()
      // 1 is the id. Make sure you specify a different ID for each notification
      notificationManager1.notify(1, build)
      Copy the code
    2. PandingIntent

      Similar to intents in name, pendingIntents tend to execute an action at the right time.

      PendingIntent provides several static methods for retrieving PendingIntent instances. You can use either the getActivity() method, getBroadcast() method, or getService() method as required.

      val intent = Intent(this, Chapter9Activity::class.java)
      // The second parameter is usually 0, the third parameter is Intent, and the fourth parameter is usually 0
      val pendingIntent = PendingIntent.getActivity(this.0, intent, 0)
      
      val build = NotificationCompat.Builder(this."like")
          .setContentTitle("This is content title")
          .setContentText("This is content text")
          .setSmallIcon(R.drawable.apple_pic)
          .setLargeIcon(
              BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_foreground)
          )
      		// Set PendingIntent and click on the effect
          .setContentIntent(pendingIntent)
      		// Click and the icon disappears
          .setAutoCancel(true)
          .build()
      notificationManager1.notify(1, build)
      Copy the code

      Cancellation notice:

      val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
      // Cancel notification. Id is the id when sending
      notificationManager.cancel(1)
      Copy the code
    3. The advanced

      • Display long text

        val build = NotificationCompat.Builder(this."like")... .setStyle(NotificationCompat.BigTextStyle().bigText(The Recently used App screen (also known as the overview screen, recent Task list, or Recently used Apps) is a system-level interface that lists activities and tasks that have been recently visited. The user can browse through the list and select the task to resume, or slide out to remove the task from the list.))... .build()Copy the code
      • Displays a larger image

        val build = NotificationCompat.Builder(this."like")... .setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources, R.drawable.banana_pic))) ... .build()Copy the code
      • Notification importance Level

        See the notification Settings in Settings for details

  2. Call the camera and album

    1. Calling the Camera

      package com.youngly.firstlineofcode.chapter9
      
      import android.app.Activity
      import android.content.Intent
      import android.graphics.Bitmap
      import android.graphics.BitmapFactory
      import android.graphics.Matrix
      import android.media.ExifInterface
      import android.net.Uri
      import android.os.Build
      import android.os.Bundle
      import android.provider.MediaStore
      import android.view.View
      import android.view.View.OnClickListener
      import android.widget.ImageView
      import android.widget.TextView
      import androidx.core.content.FileProvider
      import com.youngly.firstlineofcode.BaseActivity
      import com.youngly.firstlineofcode.R
      import java.io.File
      
      class CameraActivity : BaseActivity(), OnClickListener {
          private val takePhotoCode = 1
          private lateinit var imageView: ImageView
          private lateinit var outputImage: File
          private lateinit var imageUri: Uri
      
          override fun onCreate(savedInstanceState: Bundle?). {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_camera)
              imageView = findViewById(R.id.imageView)
              findViewById<TextView>(R.id.takePhoto).setOnClickListener(this)}override fun onClick(v: View?). {
              ExternalCacheDir /sdcard/Android/data/
                
                 /cache
                
              // You do not need to apply for SD permission to read or write storage areas associated with applications
              outputImage = File(externalCacheDir, "camara_image.jpg")
              if (outputImage.exists()) {
                  outputImage.delete()
              }
              outputImage.createNewFile()
              // Starting with Android 7.0, it is considered unsafe to use urIs directly from local real paths.
              imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                  // The second argument can be any unique string
                  FileProvider.getUriForFile(
                      this."com.youngly.firstlineofcode.fileprovider",
                      outputImage
                  )
              } else {
                  // Convert the File object to the Uri object
                  Uri.fromFile(outputImage)
              }
              val intent = Intent("android.media.action.IMAGE_CAPTURE")
              intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
              startActivityForResult(intent, takePhotoCode)
          }
      
          override fun onActivityResult(requestCode: Int, resultCode: Int.data: Intent?). {
              super.onActivityResult(requestCode, resultCode, data)
              when (requestCode) {
                  takePhotoCode -> {
                      if (resultCode == Activity.RESULT_OK) {
                          val bitmap =
                              BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
                          imageView.setImageBitmap(rotateIfRequired(bitmap))
                      }
                  }
              }
          }
      
          private fun rotateIfRequired(bitmap: Bitmap): Bitmap {
              val exifInterface = ExifInterface(outputImage.path)
              val orientation = exifInterface.getAttributeInt(
                  ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL
              )
              return when (orientation) {
                  ExifInterface.ORIENTATION_ROTATE_90 -> rotateBitmap(bitmap, 90)
                  ExifInterface.ORIENTATION_ROTATE_180 -> rotateBitmap(bitmap, 180)
                  ExifInterface.ORIENTATION_ROTATE_270 -> rotateBitmap(bitmap, 270)
                  else -> bitmap
              }
          }
      
          private fun rotateBitmap(bitmap: Bitmap, degree: Int): Bitmap {
              val matrix = Matrix()
              matrix.postRotate(degree.toFloat())
              val createBitmap =
                  Bitmap.createBitmap(bitmap, 0.0, bitmap.width, bitmap.height, matrix, true)
              // Recycle bitmaps that are no longer needed
              bitmap.recycle()
              return createBitmap
          }
      }
      Copy the code
      // Add the following configuration to manifest.xml<provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="com.youngly.firstlineofcode.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data
              android:name="android.support.FILE_PROVIDER_PATHS"
              android:resource="@xml/file_paths" />
      </provider>
      Copy the code

      Create the file_paths.xml file

      
                <paths xmlns:android="http://schemas.android.com/apk/res/android">/ / the name arbitrarily<external-path name="camara_image.jpg" path="/" /></paths>
      Copy the code
    2. Select the file from the album

      val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
      intent.addCategory(Intent.CATEGORY_OPENABLE)
      intent.type = "image/*"
      startActivityForResult(intent, fromAlbum)
      Copy the code
      if (resultCode == Activity.RESULT_OK && data! =null) {
          data.data? .let {val bitmapFromUri = getBitmapFromUri(it)
              imageView.setImageBitmap(bitmapFromUri)
          }
      }
      Copy the code
      private fun getBitmapFromUri(uri: Uri)  = contentResolver.openFileDescriptor(uri, "r")? .use { BitmapFactory.decodeFileDescriptor(it.fileDescriptor) }Copy the code
  3. Playing multimedia Files

    package com.youngly.firstlineofcode.chapter9
    
    import android.media.MediaPlayer
    import android.net.Uri
    import android.os.Bundle
    import android.provider.MediaStore
    import android.view.View
    import android.widget.VideoView
    import com.youngly.firstlineofcode.BaseActivity
    import com.youngly.firstlineofcode.R
    
    class MediaActivity : BaseActivity() {
        private val mediaPlayer = MediaPlayer()
        private lateinit var videoView:VideoView
    
        override fun onCreate(savedInstanceState: Bundle?). {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_media)
            videoView = findViewById<VideoView>(R.id.videoView)
            initMediaPlayer()
        }
    
        private fun initMediaPlayer(a) {
            val openFd = assets.openFd("Jacky Cheung - Trouble song.mp3")
            mediaPlayer.setDataSource(openFd.fileDescriptor, openFd.startOffset, openFd.length)
            mediaPlayer.prepare()
    
            val parse = Uri.parse("android.resource:://$packageName/${R.raw.screen}")
            videoView.setVideoURI(parse)
        }
    
        fun start(view: View) {
            if(! mediaPlayer.isPlaying) { mediaPlayer.start() } }fun pause(view: View) {
            if (mediaPlayer.isPlaying) {
                mediaPlayer.pause()
            }
        }
        fun stop(view: View) {
            if (mediaPlayer.isPlaying) {
                mediaPlayer.stop()
            }
        }
    
        fun vStart(view: View) {
            if(! videoView.isPlaying) { videoView.start() } }fun vPause(view: View) {
            if (videoView.isPlaying) {
                videoView.pause()
            }
        }
        fun vStop(view: View) {
            if (videoView.isPlaying) {
                videoView.resume()
            }
        }
    
        override fun onDestroy(a) {
            super.onDestroy()
          	// Release resources
            mediaPlayer.stop()
            mediaPlayer.release()
            videoView.suspend()}}Copy the code
  4. Kotlin classroom

    Infix function

    infix fun String.beginWith(prefix:String)= startsWith(prefix)
    Copy the code
    if ("hello" beginWith "1") {
      // todo
    }
    Copy the code

    The Infix function allows us to remove computer-specific syntax such as decimals, parentheses, and so on from function calls.

    Limitations:

    1. Cannot be defined as a top-level function. It must be a member function of a class or can be defined as an extension function to a class
    2. The infix function must accept only one function