Android 基础功能例子
一、相机
val contentValues = ContentValues()
val fileName = "IMG_${System.currentTimeMillis()}.jpg"//拍摄的照片的命名
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName)//名字
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures")//照片存储的相对路径位置
val uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)//相机
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
startActivity(intent)
二、打开其他应用
打开acticity
主Activity
val intent: Intent = Intent(this, SecondActivity::class.java)
intent.putExtra("MainActivityData", "I am MainActivity")//以键值对的形式携带数据
startActivityForResult(intent, resquest_code)//resquest_code为从另一个Activity返回时的idoverride fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when (requestCode) {resquest_code -> if (resultCode == RESULT_OK) {val returnData = data?.getStringExtra("SecondActivityData")//打开的Activity关闭时携带的数据Log.d(TAG, "the return data is $returnData")}}
}另一个Activityval mainActivityData = intent.getStringExtra("MainActivityData")//主Activity携带的数据Log.d(TAG, "the data is $mainActivityData")
//返回val intent = Intent()intent.putExtra("SecondActivityData", "I am SecondActivity")//返回时传递的数据setResult(RESULT_OK, intent)finish()
打开另一个应用时可通过包名打开,则打开的是默认页面,也可通过包名+活动名打开特定的页面
pm list packages//当前设备下的所有包名,adb shell下
pm list packages | grep //查找与关键字相匹配的包名,adb shell下
adb shell dumpsys window/activity | findstr mCurrentFocus//查找当前应用的包名或页面活动名
//通过包名
PackageManager packageManager = getPackageManager();
intent = packageManager.getLaunchIntentForPackage("com.example.tts");
if(intent != null ) { //如果没有默认打开的页面intent会为空startActivity(intent);
}
//包名+活动名
//打开的活动页面需要其属性在AndroidManifest.xml中的Export = “true”;通过resolveActivity可判断
intent = new Intent();
ComponentName componentName = new ComponentName("包名","活动名");
intent.setComponent(componentName);
if(inetnt.resolveActivityInfo(getPackageManager(),PackagerManager.MATCH_DEFAULT_ONLY) !=null) {startActivity(intent);
}
三、定时器
1.Timer
//匿名内部类方式Timer().schedule(object : TimerTask() {override fun run() {Log.d("1233", "4566")}}, Date(), 1000)//每隔一秒执行一次,不传第二个参数则只执行一次,第二个参数设置具体时间则在该时间后开始每隔一秒执行一次
2.Handler
val handler = Handler()
mRunnable = object:Runnable {//可转化为Lambda表达式override fun run() {mChangeValue++mListener?.onChanged(mChangeValue)handler.postDelayed(mRunnable, 2000)//实现一直定时功能}
}
handler.postDelayed(mRunable,2000)
四、对话框
//极简风格,仅做提示val dialog = AlertDialog.Builder(this)dialog.setMessage("test")dialog.show()
//带有选择的对话框val dialog = AlertDialog.Builder(this)dialog.setTitle("dialog")dialog.setTitle("test")dialog.setCancelable(false)//点击物理返回键对话框显示与否dialog.setPositiveButton("OK", object : DialogInterface.OnClickListener {override fun onClick(dialog: DialogInterface?, which: Int) {Log.d("MAIN", "OK")}})dialog.setNegativeButton("CANCEL", object : DialogInterface.OnClickListener {override fun onClick(dialog: DialogInterface?, which: Int) {Log.d("MAIN", "CANCEL")}})dialog.show()
五、通知栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//安卓8以上val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager//创建通知管理器val channel =NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT)//通知渠道,id作为发出通知时选择从哪个渠道发出通知,name为该渠道的名称,可以手动选择关闭或打开该渠道,第三个参数为优先级manager.createNotificationChannel(channel)val channelHigh =NotificationChannel("high", "High", NotificationManager.IMPORTANCE_HIGH)manager.createNotificationChannel(channelHigh)}val intent = Intent(this, NotificationActivity::class.java)//打开通知后跳转的详情页面val pendingIntent = PendingIntent.getActivity(this, 0, intent, FLAG_MUTABLE)//通知的点按操作响应val notification = NotificationCompat.Builder(this, "high").setContentTitle("Title").setContentText("content text").setContentIntent(pendingIntent).setPriority(NotificationCompat.PRIORITY_HIGH).setSmallIcon(R.mipmap.ic_launcher).setAutoCancel(true)//点击后自动移除通知.build()manager.notify(1, notification)//通知的唯一id
六、蓝牙
获取蓝牙的一些状态,如打开,关闭,连接,断连等
添加权限 AndroidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
蓝牙的状态主要是以广播的形式传递
val intentFilter = IntentFilter()intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)broadcastReceiver = BluetoothBroadcatsReceiver()registerReceiver(broadcastReceiver, intentFilter)inner class BluetoothBroadcatsReceiver : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {when (intent?.action) {BluetoothDevice.ACTION_ACL_CONNECTED -> {Log.d("MAIN", "连接")}BluetoothDevice.ACTION_ACL_DISCONNECTED -> {Log.d("MAIN", "断连")}BluetoothAdapter.ACTION_STATE_CHANGED -> when (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)) {BluetoothAdapter.STATE_ON -> Toast.makeText(context, "蓝牙已打开", Toast.LENGTH_LONG).show()BluetoothAdapter.STATE_OFF -> Toast.makeText(context, "蓝牙已断开", Toast.LENGTH_LONG).show()}}}}//获取当前连接的设备fun getConnectedBtDevice(): List<Int> {val deviceList = mutableListOf<Int>()val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()//获取蓝牙适配器val bondedDevices = bluetoothAdapter.bondedDevices//得到已匹配的蓝牙设备列表if (bondedDevices != null && bondedDevices.size > 0) {for (bondedDevice in bondedDevices) {try {//使用反射调用被隐藏的方法val isConnectedMethod =BluetoothDevice::class.java.getDeclaredMethod("isConnected")isConnectedMethod.isAccessible = trueval isConnected =isConnectedMethod.invoke(bondedDevice) as Booleanif (isConnected) {deviceList.add(bondedDevice.type)}} catch (e: NoSuchMethodException) {e.printStackTrace()} catch (e: IllegalAccessException) {e.printStackTrace()} catch (e: InvocationTargetException) {e.printStackTrace()}}}return deviceList}//获取蓝牙配置中一些协议的连接状态
val adapter = BluetoothAdapter.getDefaultAdapter()
val a2dp = adapter.getProfileConnectionState(BluetoothProfile.A2DP) == BluetoothAdapter.STATE_CONNECTED
val headset = adapter.getProfileConnectionState(BluetoothProfile.HEADSET) == BluetoothAdapter.STATE_CONNECTED
七、音频播放
本地文件或raw下的资源文件。如果是本地文件需要获取文件的绝对路径,如果文件处于data外部则需要申请所有文件的读写权限——ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION。
mMediaPlayer = MediaPlayer()val file: AssetFileDescriptor = context.resources.openRawResourceFd(R.raw.stop)mMediaPlayer.setDataSource(file.fileDescriptor, file.startOffset, file.length)file.close()mMediaPlayer.prepare()//同步,prepareAsync()-异步mMediaPlayer.setOnCompletionListener(object : OnCompletionListener{//可转化为简洁的Lambda表达式override fun onCompletion(mp: MediaPlayer?) {Log.d("VOICE","播放完毕")}})//一些其他接口:
start()开始播放
stop()停止播放,停止后无法再播放,出发再进行相关设置
pause()暂停播放,暂停后再开始播放从原来的位置继续
isPlaying()是否正在播放
八、权限申请
1.在AndrIodManifest.xml中申请,例如:
2.运行时申请:
if (ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,arrayOf(Manifest.permission.CALL_PHONE), 1)
} else {call()//已申请权限了执行的操作
}override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {1 -> {if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {call()} else {Toast.makeText(this, "You denied the permission",Toast.LENGTH_SHORT).show()}
}
先判断用户是不是已经给过我们授权了,借助ContextCompat.checkSelfPermission()方法。checkSelfPermission()方法接收两个参数:第一个参数是Context;第二个参数是具体的权限名。
ActivityCompat.requestPermissions()方法向用户申请授权。requestPermissions()方法接收3个参数:第一个参数要求是Activity的实例;第二个参数是一个String数组,我们把要申请的权限名放在数组中即可;第三个参数是请求码,只要是唯一值就可以了。