无编辑摘要 |
|||
(未显示同一用户的15个中间版本) | |||
第3行: | 第3行: | ||
==项目中引用MPChartLib== | ==项目中引用MPChartLib== | ||
1、 将MPChartLib文件夹拷贝到项目根目录 | 1、 将MPChartLib文件夹拷贝到项目根目录 | ||
2、在根目录里的settings.gradle里增加include ':app', ':MPChartLib' | 2、在根目录里的settings.gradle里增加include ':app', ':MPChartLib' | ||
3、将文件MPChartLib.aar拷贝到libs文件夹里 | 3、将文件MPChartLib.aar拷贝到libs文件夹里 | ||
4、在build.grade(app)中增加 | 4、在build.grade(app)中增加 | ||
dependencies { | dependencies { | ||
implementation project(':MPChartLib') | implementation project(':MPChartLib') | ||
第13行: | 第17行: | ||
增加权限 | 增加权限 | ||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> | ||
注册消息接收 | 注册消息接收 | ||
<receiver android:name=".BootBroadcastReceiver"> | |||
<intent-filter> | <receiver android:name=".BootBroadcastReceiver"> | ||
<action android:name="android.intent.action.BOOT_COMPLETED" /> | |||
</intent-filter> | <intent-filter> | ||
<action android:name="android.intent.action.BOOT_COMPLETED" /> | |||
</intent-filter> | |||
</receiver> | </receiver> | ||
消息接收函数 | 消息接收函数 | ||
class BootBroadcastReceiver: BroadcastReceiver() { | |||
override public fun onReceive(context: Context, intent: Intent) { | class BootBroadcastReceiver: BroadcastReceiver() { | ||
val mBootIntent = Intent(context, MainActivity::class.java) | |||
mBootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | override public fun onReceive(context: Context, intent: Intent) { | ||
context.startActivity(mBootIntent) | |||
} | val mBootIntent = Intent(context, MainActivity::class.java) | ||
mBootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | |||
context.startActivity(mBootIntent) | |||
} | |||
} | } | ||
==获取位置信息(kotlin)== | ==获取位置信息(kotlin)== | ||
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager | val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager | ||
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) | |||
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) | |||
If (location != null) { | |||
val sb = StringBuffer() | val sb = StringBuffer() | ||
sb.append('实时的位置信息:经度:') | sb.append('实时的位置信息:经度:') | ||
sb.append(location.longitude) | sb.append(location.longitude) | ||
sb.append('纬度:') | sb.append('纬度:') | ||
sb.append(location.latitude) | sb.append(location.latitude) | ||
sb.append('高度:') | sb.append('高度:') | ||
sb.append(location.altitude) | sb.append(location.altitude) | ||
sb.append('速度:') | sb.append('速度:') | ||
sb.append(location.speed) | sb.append(location.speed) | ||
sb.append('方向:') | sb.append('方向:') | ||
sb.append(location.bearing) | sb.append(location.bearing) | ||
sb.append('精度:') | sb.append('精度:') | ||
sb.append(location.accuracy) | sb.append(location.accuracy) | ||
Toast.makeText(applicationContext, sb.toString(), Toast.LENGTH_LONG).show() | Toast.makeText(applicationContext, sb.toString(), Toast.LENGTH_LONG).show() | ||
} | } | ||
添加权限 | 添加权限 | ||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> | <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> | ||
==发送Notification消息(kotlin)== | ==发送Notification消息(kotlin)== | ||
fun sendNotification(channel_id:String ,channle_name:String,nTitle:String,nContentText:String,id:Int){ | fun sendNotification(channel_id:String ,channle_name:String,nTitle:String,nContentText:String,id:Int){ | ||
var notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager | |||
var notification: Notification? = null | var notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager | ||
//val intent = Intent(Intent.ACTION_VIEW, Uri.parse('http://www.baidu.com/')) | |||
//val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0) | var notification: Notification? = null | ||
//如需链接到网站使用注释代码 | |||
val intent = Intent() | //val intent = Intent(Intent.ACTION_VIEW, Uri.parse('http://www.baidu.com/')) | ||
intent.setClass(this@MainActivity, MainActivity::class. | |||
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0) | //val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0) | ||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |||
val mChannel = NotificationChannel(channel_id, channle_name, NotificationManager.IMPORTANCE_LOW) | //如需链接到网站使用注释代码 | ||
notificationManager.createNotificationChannel(mChannel) | |||
notification = Notification.Builder(this) | val intent = Intent() | ||
.setChannelId(channel_id) | |||
.setContentTitle(nTitle) | intent.setClass(this@MainActivity, MainActivity::class. | ||
.setContentText(nContentText) | |||
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0) | |||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |||
val mChannel = NotificationChannel(channel_id, channle_name, NotificationManager.IMPORTANCE_LOW) notificationManager.createNotificationChannel(mChannel) | |||
notification = Notification.Builder(this) .setChannelId(channel_id) | |||
.setContentTitle(nTitle) .setContentText(nContentText) | |||
.setContentIntent(pendingIntent) | .setContentIntent(pendingIntent) | ||
.setSmallIcon(R.drawable.house).build() | .setSmallIcon(R.drawable.house).build() | ||
} else { | |||
val notificationBuilder = NotificationCompat.Builder(this) | } | ||
.setContentTitle(nTitle) | |||
.setContentText(nContentText) | else { | ||
.setSmallIcon(R.drawable.house) | |||
.setOngoing(true) | val notificationBuilder = NotificationCompat.Builder(this) | ||
.setContentTitle(nTitle) | |||
.setContentText(nContentText) | |||
.setSmallIcon(R.drawable.house) | |||
.setOngoing(true) | |||
//.setChannel(id)//无效 | //.setChannel(id)//无效 | ||
notification = notificationBuilder.build() | |||
notification = notificationBuilder.build() } | |||
notificationManager.notify(id, notification) | notificationManager.notify(id, notification) | ||
} | } | ||
第85行: | 第135行: | ||
==禁止使用http链接解决方法== | ==禁止使用http链接解决方法== | ||
访问网络时报异常 | 访问网络时报异常 | ||
Cleartext HTTP traffic to not permitted | Cleartext HTTP traffic to not permitted | ||
在<application标签里增加android:usesCleartextTraffic="true"即可 | 在<application标签里增加android:usesCleartextTraffic="true"即可 | ||
==bitmap缩小显示== | ==bitmap缩小显示== | ||
var matrix = Matrix() | var matrix = Matrix() | ||
matrix.postScale(0.3f,0.3f)//长和宽放大缩小的比例 | |||
matrix.postScale(0.3f,0.3f)//长和宽放大缩小的比例 | |||
val resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true) | val resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true) | ||
==textview 连续左移== | ==textview 连续左移== | ||
设置一下参数,自动连续左移动 | 设置一下参数,自动连续左移动 | ||
android:ellipsize="marquee" | |||
android:focusable="auto" | android:ellipsize="marquee" | ||
android:focusableInTouchMode="true" | |||
android:marqueeRepeatLimit="marquee_forever" | android:focusable="auto" | ||
android:scrollHorizontally="true" | |||
android:focusableInTouchMode="true" | |||
android:marqueeRepeatLimit="marquee_forever" | |||
android:scrollHorizontally="true" | |||
android:singleLine="true" | android:singleLine="true" | ||
==useAndroidx Error== | ==useAndroidx Error== | ||
编译报错 This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled. | 编译报错 | ||
This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled. | |||
在gradle.propeties文件里增加如下语句,允许AnsiroidX | 在gradle.propeties文件里增加如下语句,允许AnsiroidX | ||
android.useAndroidX=true | android.useAndroidX=true | ||
==post获取数据(kotlin)== | ==post获取数据(kotlin)== | ||
Thread(Runnable { | Thread(Runnable { | ||
val toMain1 = mAppMesHandler.obtainMessage() | |||
val toMain1 = mAppMesHandler.obtainMessage() | |||
toMain1.arg1 = 1 | toMain1.arg1 = 1 | ||
var conn: HttpURLConnection? = null | var conn: HttpURLConnection? = null | ||
var urlString = "http://server/new.php" | |||
try { | var urlString = "http://server/new.php" | ||
conn = URL(urlString).openConnection() as HttpURLConnection | |||
conn.requestMethod = "POST" // 指定POST请求 | try { | ||
conn = URL(urlString).openConnection() as HttpURLConnection | |||
conn.requestMethod = "POST" // 指定POST请求 | |||
conn.doOutput = true // 设置请求过程可以传递参数给服务器 | conn.doOutput = true // 设置请求过程可以传递参数给服务器 | ||
// post请求参数 | // post请求参数 | ||
val param = String.format("name=%s&age=%s&action=%s", "fengxueyan", "23", "query") | |||
DataOutputStream(conn.outputStream).use { os -> | val param = String.format("name=%s&age=%s&action=%s", "fengxueyan", "23", "query") DataOutputStream(conn.outputStream).use { os -> | ||
os.writeBytes(param) | |||
} | os.writeBytes(param) | ||
} | |||
conn.connect() | conn.connect() | ||
conn.inputStream.use { input -> | |||
conn.inputStream.use { input -> | |||
val data = input.bufferedReader().readText() | val data = input.bufferedReader().readText() | ||
toMain1.obj = data.toString() | toMain1.obj = data.toString() | ||
} | } | ||
} catch (e: Exception) { | |||
toMain1.obj = e.toString() | } | ||
} finally { | |||
conn?.disconnect() | catch (e: Exception) { | ||
toMain1.obj = e.toString() | |||
} | |||
finally { | |||
conn?.disconnect() | |||
} | } | ||
第139行: | 第224行: | ||
//访问网络必须使用线程,而且线程不允许更新UI | |||
val mAppMesHandler = object : Handler() { | //访问网络必须使用线程,而且线程不允许更新UI | ||
override fun handleMessage(msg: Message) { | |||
if(msg.arg1 == 1){ | val mAppMesHandler = object : Handler() { | ||
override fun handleMessage(msg: Message) { | |||
if(msg.arg1 == 1){ | |||
var hList0 = msg.obj as String | var hList0 = msg.obj as String | ||
textView.setText(hList0) | textView.setText(hList0) | ||
// Toast.makeText(applicationContext,hList0,Toast.LENGTH_LONG).show() | |||
// Toast.makeText(applicationContext,hList0,Toast.LENGTH_LONG).show() | |||
} | } | ||
} | |||
} | } | ||
==时间日期选择== | ==时间日期选择== | ||
<TimePicker | <TimePicker | ||
android:id="@+id/ptime" | android:id="@+id/ptime" | ||
android:layout_width="310dp" | |||
android:layout_height="347dp" | android:layout_width="310dp" | ||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | android:layout_height="347dp" | ||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/button2" /> | app:layout_constraintTop_toBottomOf="@+id/button2" /> | ||
textView.setText(ptime.hour.toString()+":"+ptime.minute.toString()) | textView.setText(ptime.hour.toString()+":"+ptime.minute.toString()) | ||
<DatePicker | <DatePicker | ||
android:id="@+id/pdate" | |||
android:layout_width="358dp" | android:id="@+id/pdate" | ||
android:layout_height="428dp" | |||
android:layout_marginTop="20dp" | android:layout_width="358dp" | ||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.566" | android:layout_height="428dp" | ||
app:layout_constraintStart_toStartOf="parent" | |||
android:layout_marginTop="20dp" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.566" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/button2" /> | app:layout_constraintTop_toBottomOf="@+id/button2" /> | ||
第201行: | 第306行: | ||
} | } | ||
Activity向Fragment传递数据直接定义函数 | Activity向Fragment传递数据直接定义函数 | ||
Fragment向Activity传递数据发送消息 | |||
val toMain1 = aHandle!!.obtainMessage() | Fragment向Activity传递数据发送消息 | ||
toMain1.obj = “message or data” | |||
val toMain1 = aHandle!!.obtainMessage() | |||
toMain1.obj = “message or data” | |||
toMain1.arg1 = 1 | toMain1.arg1 = 1 | ||
aHandle!!.sendMessage(toMain1) | aHandle!!.sendMessage(toMain1) | ||
==实现扫码二维码(kotlin)== | ==实现扫码二维码(kotlin)== | ||
dependencies增加引用 | dependencies增加引用 | ||
implementation 'com.hongyelinggu:scancode:1.0.0' | implementation 'com.hongyelinggu:scancode:1.0.0' | ||
申请相机权限 | 申请相机权限 | ||
<uses-permission android:name="android.permission.CAMERA"/> | |||
val REQUEST_EXTERNAL_STORAGE = 1234 | <uses-permission android:name="android.permission.CAMERA"/> | ||
if (ActivityCompat.checkSelfPermission(this, | |||
"android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ) { | val REQUEST_EXTERNAL_STORAGE = 1234 | ||
if (ActivityCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ) { | |||
ActivityCompat.requestPermissions(this, | ActivityCompat.requestPermissions(this, | ||
arrayOf(Manifest.permission.CAMERA), REQUEST_EXTERNAL_STORAGE) | arrayOf(Manifest.permission.CAMERA), REQUEST_EXTERNAL_STORAGE) | ||
} | } | ||
else{ | else{ | ||
第227行: | 第342行: | ||
startActivityForResult(Intent(this@MainActivity, CommonScanActivity::class.java), 1) | startActivityForResult(Intent(this@MainActivity, CommonScanActivity::class.java), 1) | ||
返回结果字符串 | 返回结果字符串 | ||
override fun onActivityResult(requestCode:Int, resultCode:Int, data:Intent?){ | |||
super.onActivityResult(requestCode, resultCode, data) | override fun onActivityResult(requestCode:Int, resultCode:Int, data:Intent?){ | ||
val rCode = data!!.extras!!.getString(Constant.REQUEST_SCAN_MODE) //得到新Activity关闭后返回的数据 | |||
super.onActivityResult(requestCode, resultCode, data) | |||
val rCode = data!!.extras!!.getString(Constant.REQUEST_SCAN_MODE) //得到新Activity关闭后返回的数据 | |||
Toast.makeText(applicationContext, rCode, Toast.LENGTH_LONG).show() | Toast.makeText(applicationContext, rCode, Toast.LENGTH_LONG).show() | ||
} | } | ||
第236行: | 第355行: | ||
写入文件 | 写入文件 | ||
val fn = filesDir.toString() + "文件名.txt" | val fn = filesDir.toString() + "文件名.txt" | ||
var fff = "文本内容" | |||
try { | var fff = "文本内容" | ||
val tfw = FileWriter(fn) | |||
tfw.write(fff) | try { | ||
val tfw = FileWriter(fn) | |||
tfw.write(fff) | |||
tfw.close() | tfw.close() | ||
Toast.makeText(applicationContext, "保存成功", Toast.LENGTH_LONG).show() | Toast.makeText(applicationContext, "保存成功", Toast.LENGTH_LONG).show() | ||
} catch (e: Exception) { | |||
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show() | } | ||
catch (e: Exception) { | |||
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show() | |||
} | } | ||
读取文件 | 读取文件 | ||
val fn = filesDir.toString() + "文件名.txt" | |||
try { | val fn = filesDir.toString() + "文件名.txt" | ||
val fb = FileReader(fn) | |||
val tv2:TextView = findViewById(R.id.textView2) | try { | ||
tv2.setText(fb.readText()) //显示到TextView | |||
fb.close() | val fb = FileReader(fn) | ||
} | |||
catch(e:Exception){ | val tv2:TextView = findViewById(R.id.textView2) | ||
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show() | |||
tv2.setText(fb.readText()) //显示到TextView | |||
fb.close() | |||
} | |||
catch(e:Exception){ | |||
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show() | |||
} | } | ||
如果路径访问需要权限 | 如果路径访问需要权限 | ||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> | |||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> | |||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> | <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> | ||
//获取sd卡读写权限 | //获取sd卡读写权限 | ||
//val REQUEST_EXTERNAL_STORAGE = 1234 | |||
if (ActivityCompat.checkSelfPermission(this, | //val REQUEST_EXTERNAL_STORAGE = 1234 | ||
"android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED ) { | |||
ActivityCompat.requestPermissions(this, | if (ActivityCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED ) { | ||
arrayOf(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE), REQUEST_EXTERNAL_STORAGE) | |||
ActivityCompat.requestPermissions(this, arrayOf(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE), REQUEST_EXTERNAL_STORAGE) | |||
} | } | ||
else{ | else{ | ||
} | } | ||
==多项选择对话框 kotlin== | ==多项选择对话框 kotlin== | ||
val builder = AlertDialog.Builder(this) | val builder = AlertDialog.Builder(this) | ||
builder.setTitle("请选择") | |||
builder.setIcon(R.drawable.ic_launcher_foreground) | builder.setTitle("请选择") | ||
builder.setIcon(R.drawable.ic_launcher_foreground) | |||
builder.setCancelable(true) | builder.setCancelable(true) | ||
val items = arrayOf("第一项", "第二项", "第三项") | val items = arrayOf("第一项", "第二项", "第三项") | ||
var selected = booleanArrayOf(true, false, true) | var selected = booleanArrayOf(true, false, true) | ||
builder.setMultiChoiceItems(items, selected) { dialog, which, isChecked -> // dialog.dismiss(); | builder.setMultiChoiceItems(items, selected) { dialog, which, isChecked -> | ||
// dialog.dismiss(); | |||
// Toast.makeText(this@MainActivity, items[which] + isChecked, Toast.LENGTH_SHORT).show() | // Toast.makeText(this@MainActivity, items[which] + isChecked, Toast.LENGTH_SHORT).show() | ||
} | } | ||
//此代码实现输入文本对话框 | //此代码实现输入文本对话框 | ||
//val filename :EditText = EditText(this) | |||
//val filename :EditText = EditText(this) | |||
//builder.setView(filename) | //builder.setView(filename) | ||
builder.setPositiveButton(" 确定发送 ") { dialogInterface, i -> | builder.setPositiveButton(" 确定发送 ") { dialogInterface, i -> | ||
val tw: TextView = findViewById(R.id.textView1) | val tw: TextView = findViewById(R.id.textView1) | ||
var sd = "" | var sd = "" | ||
for (i in 0 until items.count()) { | |||
if (selected[i]) | for (i in 0 until items.count()) { | ||
sd += items[i] | |||
} | if (selected[i]) | ||
tw.setText(sd) | |||
sd += items[i] | |||
} | |||
tw.setText(sd) | |||
Toast.makeText(this@MainActivity, sd, Toast.LENGTH_SHORT).show() | Toast.makeText(this@MainActivity, sd, Toast.LENGTH_SHORT).show() | ||
//tw.setText(filename.text.toString()) | //tw.setText(filename.text.toString()) | ||
} | |||
builder.setNegativeButton("取消发送") { dialogInterface, i -> | } | ||
builder.setNegativeButton("取消发送") { dialogInterface, i -> | |||
// finish() | // finish() | ||
} | |||
builder.show() | builder.show() | ||
==OptionsMenu kotlin== | ==OptionsMenu kotlin== | ||
app 右键 new=》android resouce file | app 右键 new=》android resouce file resouce type 选择Menu | ||
resouce type 选择Menu | |||
创建菜单项目,编辑ID和title | 创建菜单项目,编辑ID和title | ||
//显示菜单 | |||
//显示菜单 | |||
override fun onCreateOptionsMenu(menu: Menu?): Boolean { | override fun onCreateOptionsMenu(menu: Menu?): Boolean { | ||
menuInflater.inflate(R.menu.mainmanu,menu) | menuInflater.inflate(R.menu.mainmanu,menu) | ||
return true | return true | ||
// return super.onCreateOptionsMenu(menu) | // return super.onCreateOptionsMenu(menu) | ||
} | } | ||
//处理菜单点击响应 | //处理菜单点击响应 | ||
override fun onOptionsItemSelected(item: MenuItem): Boolean { | override fun onOptionsItemSelected(item: MenuItem): Boolean { | ||
if(item?.itemId == R.id.menu_exit){ | if(item?.itemId == R.id.menu_exit){ | ||
finish() | |||
} | finish() | ||
if(item?.itemId == R.id.menu_upate){ | |||
Toast.makeText(this,"system update",Toast.LENGTH_LONG).show() | } | ||
if(item?.itemId == R.id.menu_upate){ | |||
Toast.makeText(this,"system update",Toast.LENGTH_LONG).show() | |||
} | } | ||
2024年3月14日 (四) 13:35的最新版本
项目中引用MPChartLib
1、 将MPChartLib文件夹拷贝到项目根目录
2、在根目录里的settings.gradle里增加include ':app', ':MPChartLib'
3、将文件MPChartLib.aar拷贝到libs文件夹里
4、在build.grade(app)中增加
dependencies { implementation project(':MPChartLib') }
设置app自动启动
增加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
注册消息接收
<receiver android:name=".BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
消息接收函数
class BootBroadcastReceiver: BroadcastReceiver() {
override public fun onReceive(context: Context, intent: Intent) {
val mBootIntent = Intent(context, MainActivity::class.java)
mBootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(mBootIntent)
}
}
获取位置信息(kotlin)
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
If (location != null) {
val sb = StringBuffer()
sb.append('实时的位置信息:经度:')
sb.append(location.longitude) sb.append('纬度:')
sb.append(location.latitude) sb.append('高度:')
sb.append(location.altitude) sb.append('速度:')
sb.append(location.speed) sb.append('方向:')
sb.append(location.bearing) sb.append('精度:')
sb.append(location.accuracy)
Toast.makeText(applicationContext, sb.toString(), Toast.LENGTH_LONG).show() }
添加权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
发送Notification消息(kotlin)
fun sendNotification(channel_id:String ,channle_name:String,nTitle:String,nContentText:String,id:Int){
var notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
var notification: Notification? = null
//val intent = Intent(Intent.ACTION_VIEW, Uri.parse('http://www.baidu.com/'))
//val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
//如需链接到网站使用注释代码
val intent = Intent()
intent.setClass(this@MainActivity, MainActivity::class.
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val mChannel = NotificationChannel(channel_id, channle_name, NotificationManager.IMPORTANCE_LOW) notificationManager.createNotificationChannel(mChannel)
notification = Notification.Builder(this) .setChannelId(channel_id) .setContentTitle(nTitle) .setContentText(nContentText)
.setContentIntent(pendingIntent) .setSmallIcon(R.drawable.house).build()
}
else {
val notificationBuilder = NotificationCompat.Builder(this)
.setContentTitle(nTitle)
.setContentText(nContentText)
.setSmallIcon(R.drawable.house)
.setOngoing(true)
//.setChannel(id)//无效
notification = notificationBuilder.build() }
notificationManager.notify(id, notification) }
禁止使用http链接解决方法
访问网络时报异常
Cleartext HTTP traffic to not permitted
在<application标签里增加android:usesCleartextTraffic="true"即可
bitmap缩小显示
var matrix = Matrix()
matrix.postScale(0.3f,0.3f)//长和宽放大缩小的比例
val resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true)
textview 连续左移
设置一下参数,自动连续左移动
android:ellipsize="marquee"
android:focusable="auto"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
useAndroidx Error
编译报错
This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled.
在gradle.propeties文件里增加如下语句,允许AnsiroidX
android.useAndroidX=true
post获取数据(kotlin)
Thread(Runnable {
val toMain1 = mAppMesHandler.obtainMessage()
toMain1.arg1 = 1
var conn: HttpURLConnection? = null
var urlString = "http://server/new.php"
try {
conn = URL(urlString).openConnection() as HttpURLConnection
conn.requestMethod = "POST" // 指定POST请求
conn.doOutput = true // 设置请求过程可以传递参数给服务器
// post请求参数
val param = String.format("name=%s&age=%s&action=%s", "fengxueyan", "23", "query") DataOutputStream(conn.outputStream).use { os ->
os.writeBytes(param)
}
conn.connect()
conn.inputStream.use { input ->
val data = input.bufferedReader().readText() toMain1.obj = data.toString()
}
}
catch (e: Exception) {
toMain1.obj = e.toString()
}
finally {
conn?.disconnect()
}
mAppMesHandler.sendMessage(toMain1) }).start()
//访问网络必须使用线程,而且线程不允许更新UI
val mAppMesHandler = object : Handler() {
override fun handleMessage(msg: Message) {
if(msg.arg1 == 1){
var hList0 = msg.obj as String textView.setText(hList0)
// Toast.makeText(applicationContext,hList0,Toast.LENGTH_LONG).show()
}
}
}
时间日期选择
<TimePicker android:id="@+id/ptime"
android:layout_width="310dp"
android:layout_height="347dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
textView.setText(ptime.hour.toString()+":"+ptime.minute.toString())
<DatePicker
android:id="@+id/pdate"
android:layout_width="358dp"
android:layout_height="428dp"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.566"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
textView.setText(pdate.year.toString()+"-"+(pdate.month+1).toString()+"-"+pdate.dayOfMonth.toString())
多个Fragment和Activity的简易数据交换方法(kotlin)
动态创建多个Fragment后,和Activity数据交换有很多种方式,消息方式简单快捷,代码量少
在Activity中定义消息处理 val mMainHandler = object : Handler() {
override fun handleMessage(msg: Message) { if (msg.arg1 == 1) { val sVerRes = msg.obj as String Toast.makeText(applicationContext, sVerRes, Toast.LENGTH_LONG).show() }
}
在Fragment里定义消息handle
private var aHandle:Handler? = null
建立初始化函数,将Activity的消息handle传入
fun setHandler(AHandler: Handler?) {
try { aHandle = AHandler } catch (e: Exception) { throw ClassCastException(context.toString() }
}
Activity向Fragment传递数据直接定义函数
Fragment向Activity传递数据发送消息
val toMain1 = aHandle!!.obtainMessage()
toMain1.obj = “message or data”
toMain1.arg1 = 1
aHandle!!.sendMessage(toMain1)
实现扫码二维码(kotlin)
dependencies增加引用
implementation 'com.hongyelinggu:scancode:1.0.0'
申请相机权限
<uses-permission android:name="android.permission.CAMERA"/>
val REQUEST_EXTERNAL_STORAGE = 1234
if (ActivityCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_EXTERNAL_STORAGE)
}
else{
}
执行扫描 startActivityForResult(Intent(this@MainActivity, CommonScanActivity::class.java), 1)
返回结果字符串
override fun onActivityResult(requestCode:Int, resultCode:Int, data:Intent?){
super.onActivityResult(requestCode, resultCode, data)
val rCode = data!!.extras!!.getString(Constant.REQUEST_SCAN_MODE) //得到新Activity关闭后返回的数据
Toast.makeText(applicationContext, rCode, Toast.LENGTH_LONG).show() }
读取写入文本文件(kotlin)
写入文件
val fn = filesDir.toString() + "文件名.txt"
var fff = "文本内容"
try {
val tfw = FileWriter(fn)
tfw.write(fff)
tfw.close()
Toast.makeText(applicationContext, "保存成功", Toast.LENGTH_LONG).show()
}
catch (e: Exception) {
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show()
}
读取文件
val fn = filesDir.toString() + "文件名.txt"
try {
val fb = FileReader(fn)
val tv2:TextView = findViewById(R.id.textView2)
tv2.setText(fb.readText()) //显示到TextView
fb.close()
}
catch(e:Exception){
Toast.makeText(applicationContext, e.toString(), Toast.LENGTH_LONG).show()
}
如果路径访问需要权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
//获取sd卡读写权限
//val REQUEST_EXTERNAL_STORAGE = 1234
if (ActivityCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(this, arrayOf(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE), REQUEST_EXTERNAL_STORAGE)
}
else{
}
多项选择对话框 kotlin
val builder = AlertDialog.Builder(this)
builder.setTitle("请选择")
builder.setIcon(R.drawable.ic_launcher_foreground)
builder.setCancelable(true)
val items = arrayOf("第一项", "第二项", "第三项")
var selected = booleanArrayOf(true, false, true)
builder.setMultiChoiceItems(items, selected) { dialog, which, isChecked ->
// dialog.dismiss();
// Toast.makeText(this@MainActivity, items[which] + isChecked, Toast.LENGTH_SHORT).show()
}
//此代码实现输入文本对话框
//val filename :EditText = EditText(this)
//builder.setView(filename)
builder.setPositiveButton(" 确定发送 ") { dialogInterface, i ->
val tw: TextView = findViewById(R.id.textView1) var sd = ""
for (i in 0 until items.count()) {
if (selected[i])
sd += items[i]
}
tw.setText(sd)
Toast.makeText(this@MainActivity, sd, Toast.LENGTH_SHORT).show()
//tw.setText(filename.text.toString())
}
builder.setNegativeButton("取消发送") { dialogInterface, i ->
// finish()
}
builder.show()
OptionsMenu kotlin
app 右键 new=》android resouce file resouce type 选择Menu
创建菜单项目,编辑ID和title
//显示菜单
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.mainmanu,menu)
return true
// return super.onCreateOptionsMenu(menu)
}
//处理菜单点击响应
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item?.itemId == R.id.menu_exit){
finish()
}
if(item?.itemId == R.id.menu_upate){
Toast.makeText(this,"system update",Toast.LENGTH_LONG).show()
}
return super.onOptionsItemSelected(item)
}
ContextMenu kotlin
app 右键 new=》android resouce file resouce type 选择Menu 创建菜单项目,编辑ID和title
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) { super.onCreateContextMenu(menu, v, menuInfo) menuInflater.inflate(R.menu.menupop,menu) menu!!.setHeaderTitle("请选择") }
重载函数
override fun onContextItemSelected(item: MenuItem): Boolean { if(item.itemId == R.id.media_route_menu_item1){ Toast.makeText(this,"11111111",Toast.LENGTH_LONG).show() } return super.onContextItemSelected(item) }
onCreate
val bt_menu: Button = findViewById(R.id.button_menu) registerForContextMenu(bt_menu) bt_menu.setOnClickListener { openContextMenu(it) }
如果在list view item弹出菜单,直接
val tv_houseList = findViewById(R.id.listview_house_list) as ListView registerForContextMenu(tv_houseList)
这样长按item自动会弹出菜单
androidstudio使用WebView显示网页(kotlin)
val wset = wview1.settings wset.javaScriptEnabled = true wview1.setWebViewClient(object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { view.loadUrl(url) return true } }) wview1.loadUrl(“http://www.baidu.com”)
在AndroidManifest.xml增加
android:usesCleartextTraffic="true"
需要添加网络权限
如果需要支持网页弹出alert:
wview1.setWebChromeClient (object : WebChromeClient() override fun onJsAlert(view: WebView,url: String,message: String,result: JsResult):Boolean{ return super.onJsAlert(view, url, message, result) } })
androidstudio使用viewPager显示多张图片并关联tabLayout(kotlin)
val mImgId = intArrayOf(R.drawable.h1, R.drawable.h2, R.drawable.h3)
val mList = ArrayList() var tabName : Array = Array(3,{""})
tabName[0] = "TAB1" tabName[1] = "TAB2" tabName[2] = "TAB3"
vpage.setAdapter(object : PagerAdapter() { override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { container.removeView(mList.get(position)) } override fun instantiateItem(container: ViewGroup, position: Int): Any { val imageView = ImageView(this@MainActivity) imageView.setImageResource(mImgId[position]) imageView.setScaleType(ImageView.ScaleType.CENTER_CROP) container.addView(imageView) mList.add(imageView) return imageView } override fun getCount(): Int { return mImgId.size } override fun isViewFromObject(view: View, `object`: Any): Boolean { return view === `object` } override fun getPageTitle(position:Int):CharSequence{ return tabName[position] }
}) tabcus.setupWithViewPager(vpage)
使用ViewPager2和TabLayout实现多frgment切换
private fun initTab(){ val viewpage = findViewById(R.id.viewpage2) as ViewPager2 viewpage.adapter = object : FragmentStateAdapter(this){ override fun getItemCount(): Int { return 3 } override fun createFragment(position: Int): Fragment { return when(position){ 0 -> myFragment() 1 -> hlistFragment() else -> hlistFragment() } } } val tabmain = findViewById(R.id.tabLayout) as TabLayout
TabLayoutMediator( tabmain, viewpage, object : TabLayoutMediator.TabConfigurationStrategy{ override fun onConfigureTab(tab: TabLayout.Tab, position: Int) { when(position){ 0 -> tab.text = "资源汇总" 1 -> tab.text = "我的房源" else -> tab.text = "房源资源库" } } }).attach()
xml文件
<com.google.android.material.tabs.TabLayout <androidx.viewpager2.widget.ViewPager2
建立Fragement list 用于访问每个动态创建的Fragment
var list_frm:ArrayList<Fragment> = ArrayList()
override fun createFragment(position: Int): Fragment { when(position){ 0 -> { val fg = myFragment() list_frm.add(fg ) return fg } 1 -> { val fg = hlistFragment() list_frm.add(fg) return fg } else -> { val fg = hlistFragment() list_frm.add(fg) return fg } } }
使用BaseAdapter为listview装入数据
class myAdapter (context: Activity,listValue:String): BaseAdapter(){ private var ct:Activity private var lv:String init { ct = context lv = listValue
} override fun getCount():Int{ val hma_list = lv.split("^") return hma_list.count() } override fun getItem(position: Int):String{ val hma_list = lv.split("^") return hma_list[position].toString() } override fun getItemId(position: Int):Long{ return position.toLong() }
override fun getView(position: Int, view: View?, parent: ViewGroup): View { val rowView = ct.layoutInflater.inflate(R.layout.layout_house_info_item, null, true) val hm_name = rowView.findViewById(R.id.tv_item_name) as TextView val hm_price = rowView.findViewById(R.id.tv_item_price) as TextView val hm_size = rowView.findViewById(R.id.tv_item_size) as TextView val hm_room = rowView.findViewById(R.id.tv_item_room) as TextView val hm_time = rowView.findViewById(R.id.tv_item_time) as TextView val hm_status = rowView.findViewById(R.id.tv_item_status) as TextView val hma_list = lv.split("^") var hma_value = hma_list[position].split("~") hm_name.text = hma_value[0] if(hma_value[12] == "2" ) hm_price.text = hma_value[4]+"/月" else hm_price.text = hma_value[2]+"万" hm_size.text = hma_value[9] +" "+ hma_value[1]+"平米" hm_room.text = hma_value[6]+"室"+hma_value[7]+"厅"+hma_value[8]+"卫 "+hma_value[5]+"层" hm_time.text = "最后跟进"+hma_value[11] return rowView } }
listview 操作
val adapter = myAdapter(this,listStr) tv_houseList.setAdapter(adapter)
让EditText不能编辑,只读
et_tel.keyListener = null
让WebView支持手机定位
静态申请权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_GPS" /> <uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" /> <uses-permission android:name="android.permission.ACCESS_LOCATION" />
动态申请权限
if (ActivityCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION), 1234) }
设置WebView参数
val wview1 = findViewById(R.id.vview1) as WebView val wset = wview1.settings wset.javaScriptEnabled = true wset.setGeolocationEnabled(true) //允许定位 wview1.setWebViewClient(object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { view.loadUrl(url) return true } })
wview1.setWebChromeClient (object : WebChromeClient() { override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult):Boolean{ return super.onJsAlert(view, url, message, result) } override fun onGeolocationPermissionsShowPrompt( origin: String?, callback: GeolocationPermissions.Callback? ) { val remember = true val builder: AlertDialog.Builder = AlertDialog.Builder(this@MainActivity) builder.setTitle("位置信息") builder.setMessage(origin + "允许获取您的地理位置信息吗?").setCancelable(true) .setPositiveButton("允许", DialogInterface.OnClickListener { dialog, id -> callback?.invoke( origin, true, remember ) }) .setNegativeButton("不允许", DialogInterface.OnClickListener { dialog, id -> callback?.invoke( origin, false, remember ) }) val alert: AlertDialog = builder.create() alert.show() } })