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返回时的id
override 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")
}
}
}
另一个Activity
val 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 = true
val isConnected =
isConnectedMethod.invoke(bondedDevice) as Boolean
if (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数组,我们把要申请的权限名放在数组中即可;第三个参数是请求码,只要是唯一值就可以了。