广播机制

  1. 分类
      • 标准广播:完全异步执行的广播,在广播发出后,所有的BroadcastReceiver同时收到
      • 有序广播:同步执行的广播,同一时刻之后一个BroadcastReceiver可以收到
  1. 接收系统广播(手机开机完成会发出一条广播、电量发生变化会发出一条广播等等)
    1. 注册BroadcastReceiver
    2. 代码中注册(动态注册 — 程序启动时才能接收)
      1. class MainActivity : AppCompactActivity() { lateinit var timeChangeReceiver: TimeChangeReceiver override fun onCreate(savedInstanceState: Bundle?) { // ... val intentFilter = IntentFilter() intentFilter.addAction("android.intent.action.TIME_TICK") // 想监听什么广播,就加什么action timeChangeReceiver = TimeChangeReceiver() registerReceiver(timeChangeReceiver, intentFilter) } override fun onDestroy() { // ... registerReceiver(timeChangeReceiver) } class TimeChangeReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { TODO("...") } } }
    3. AndroidManifest.xml中注册(静态注册 — 程序)
      1. // AndroidManifest.xml <manifest ....> // 权限声明,安卓规定,如果不声明就会直接崩溃 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"> <application ...> ... <receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </> </> </> </> // class BootCompleteReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { TODO("...") } }
  1. 自定义广播
    1. 发送标准广播
      1. class MainActivity : AppCompactActivity() { // ... override fun onCreate(savedInstanceState: Bundle?) { // ... button.setOnClickListener { val intent = Intent("com.example.broadcasttest.MY_BROADCAST") intent.setPackage(packageName) sendBroadcast(intent) } } }
    2. 接收
      1. 自定义广播都是隐式广播,发送标准广播时使用setPackage(packageName)将隐式广播变成一条显式广播,非原则静态注册的BroadcastReceiver无法接收到这条广播
    3. 发送有序广播
      1. // a中sendBroadcast(intent)改为 sendOrderedBroadcast(intent, null)
    4. 接收有序广播
      1. // AndroidManifest.xml ... <intent-filter android:priority="100"> <action android:name="com.example.broadcasttest.MY_BROADCAST" /> </> ... // Receiver中可以 ... override fun onReceive(context: Context, intent: Intent) { TODO("...") abortBroadcast() } ...

      数据持久化

      三种方式
    5. 文件存储
        1. Context类提供了一个`openFileOutput()`方法,这个方法接收文件名和文件的操作模式两个参数。操作模式有MODE_PRIVATE(若文件存在则覆盖)和MODE_APPEND(文件存在就追加)。所有文件默认存储到/data/data/<package name>/files/下
          fun save(inputText: String) { try { val output = openFileOutput("data", Context.MODE_PRIVATE) val writer = BufferedWriter(OutputStreamWriter(output)) writer.use { // use保证使用完之后将流关闭,类似python的with it.write(inputText) } } catch (e: IOException) { e.printStackTrace() } }
        1. Context类提供了一个`openFileInput()`方法,只接收要读取的文件名一个参数,回去默认路径下加载这个文件,并返回一个流对象。
          fun load() { val content = StringBuilder() try { val input = openFileInput("data") val reader = BufferedReader(InputStreamReader(input)) reader.use { reader.forEachLine { content.append(it) } } } catch (e: IOException) { e.printStackTrace() } return content.toString() }
    6. SharedPreferences存储 — 使用键值对
      1. 获取SharedPreferences对象
        1. Context类中的getSharedPreferences()方法
          1. 接收两个参数:
            • SharedPreferences文件的名称,路径/data/data/<package name>/shared_prefs/目录下
            • 操作模式,之后默认的MODE_PRIVATE可选
        2. Activity类中的getPreferences()方法
          1. 只接收一个参数:操作模式。默认自动将当前Activity类型作为SharedPreferences文件名
        1. 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象
        2. 向SharedPreferences.Editor对象中添加数据,使用putInt(), putT()方法。T表示数据类型。
        3. 调用apply()将添加的数据提交
        4. val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit() editor.putString("name", "Tom") editor.putInt("age", 28) editor.apply()
        1. getT()
          接收两个参数
          • 找不到键的默认值
    7. SQLite - SQLiteOpenHelper抽象类
      1. onCreate() onUpgrade()
      2. 创建数据库
        1. 下面两种方法均可创建或打开一个数据库,并返回一个可对数据库进行读写操作的对象。数据库文件会存放在/data/data/<package name>/databases/下
          • getReadableDatabase(),若数据库不可写入,返回的对象会以只读方式打开数据库
          • getWritableDatabase(),若数据库不可写入,则抛异常
      3. 升级数据库

ContextProvider

 

多媒体

Notification

  1. 创建通知渠道 - Android version ≥ 8.0
    1. 通知渠道就是每条通知都要属于一个对应的渠道。每个应用程序都可以自由地创建当前应用拥有哪些通知渠道,但是这些通知渠道的控制权是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动或者是否要关闭这个渠道的通知。
    2. NotificationManager
      1. val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    3. NotificationChannel
      1. // 版本判断 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 渠道id、渠道名称、重要等级 // 通知的重要等级有IMPORTANCE_HIGH/IMPORTANCE_DEFAULT/IMPORTANCE_LOW/IMPORTANCE_MI几种 val channel = NotificationChannel(channelId, channelName, importance) mannager.createNotificationChannel(channel) }
  1. 通知的用法
    1. 通知的用法还是比较灵活的,既可以在Activity里创建,也可以在BroadcastReceiver里创建,当然还可以在后面我们即将学习的Service里创建。
      val notification = NotificationCompat.Builder(context, channelId) .setContentTitle("title") .setContentText("text") .setSmallIcon(R.drawable.small_icon) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.large_icon)) .build() manager.notify(1, notification)
  1. 通知可点击
    1. 可以把PendingIntent简单地理解为延迟执行的Intent
      val intent = Intent(this, MainActivity::class.java) val pi = PendingIntent.getActivity(this, 0, intent, 0) val notion = // ... .setContentIntent(pi) .setAutoCancel(true) // 点击后消失 // ...
  1. setStyle()

调用摄像头和相册

  • 摄像头
      1. 创建储存图片的对象
      1. 隐式intent调用拍摄
      1. 在结果回调onActivityResult()中处理图片
  • 选择相册图片

播放多媒体文件

  • 音频
  • 视频

Service

badge