Android studio:修订间差异

来自OSSmedia
(创建页面,内容为“<nowiki>分类:编程</nowiki>”)
 
 
(未显示同一用户的16个中间版本)
第1行: 第1行:
<nowiki>[[分类:编程]]</nowiki>
[[分类:编程]]
 
==项目中引用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()
                }
            })

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()
               }
           })