A.开发注意事项
- 在产品提出原型的时候,先理清思路,把所有的可能逻辑都写出来,而不是口头描述,在后续实现的过程中还会有后续的逻辑补上,全部都要有文字描述
B.Android Studio炸了
- Android Studio 3.5 xml文件中 格式化代码 文件错乱问题
- Android Studio pull push一直提示输入密码
- 编译的时候出现了文件lock问题 -> 根据提示删除所有的本地lock文件和项目build文件
1.使用Kotlin但是直接使用控件id进行操作提示无法找到
项目build.gradle中添加 org.jetbrains.kotlin:kotlin-android-extensions:1.3.41
模块build.gradle中添加插件apply plugin: 'kotlin-android-extensions'
2.ARouter提示找不到路径"W/ARouter::: ARouter::There is no route match the path [/xxx/xxx], in group [xxx][ ]"
- 首先是由于都是字符串作为标记,查看是否是 <u>字符串写错了</u>,是否配置了两级目录,一般是自信手打造成的,相信我还是cv操作更为稳妥,或者使用String常量来表示
- 是否在 <u>每一个需要使用ARouter的模块中添加了kapt的依赖</u>,查看文章标题一,这个是我发现遇到最多的问题
- 因为都是在多个模块中,那么是不是在使用模块化和插件化的过程中,<u>有没有把该模块依赖到主模块(app模块中)中,例如三个模块app,moduleA,moduleB,moduleA和moduleB都需要依赖到app模块中,这样moduleA和moduleB之间才能相互跳转</u>,觉得真的没问题的时候就是这个问题
- 开启调试模式,开启日志,运行app,查看ARouter是否发现了目标
D/ARouter::: The group [app] has already been loaded, trigger by [/app/MainActivity][ ] 没有发现目标,那就还是配置的问题 - 最后看下是不是真的有这个路径的页面,是否真的注册了,有没有可能手贱删掉了注册中的一个字符,注解是不是@Router,path有没有写等等一些细节
3.在AndroidStudio正在构建的时候强制关闭AndroidStudio导致下次无法构建工程
进入提示的文件夹,将该文件夹下和该文件夹的父文件夹下所有子文件夹中的所有的.lock文件全部删除
4.targetSdkVersion 28无法请求http
- 检查是否有网络权限
- 在清单文件中application节点下添加
android:usesCleartextTraffic="true"
- 这个最有效 强烈推荐 ==> 修改targetSdkVersion 27
5.权限适配,安卓6.0以下并不是在清单文件中写上权限就默认获取到了权限的
魅族在自带的设置中有权限设置,vivo有爱管家进行权限管理,并且使用ActivityCompact去查看权限,返回已经获取,使用工具类通过查看是否可以使用来判断是否有权限,当然可以去各自的官网来查看如何适配权限
@JvmStatic
val isAudioUsable: Boolean
get() {
val audioFormat = AudioFormat.ENCODING_PCM_16BIT
val channelConfig = AudioFormat.CHANNEL_IN_STEREO
val sampleRateInHz = 44100
val bufferSizeInBytes = AudioRecord.getMinBufferSize(
sampleRateInHz,
channelConfig, audioFormat
)
val audioSource = MediaRecorder.AudioSource.MIC
val audioRecord = AudioRecord(
audioSource, sampleRateInHz,
channelConfig, audioFormat, bufferSizeInBytes
)
try {
audioRecord.startRecording()
} catch (e: IllegalStateException) {
e.printStackTrace()
return false
}
if (audioRecord.recordingState != AudioRecord.RECORDSTATE_RECORDING) {
return false
}
audioRecord.stop()
audioRecord.release()
return true
}
/**
* 判断是否摄像头可以使用
*
* @return 是否可以使用
* setParameters 是针对魅族MX5 做的。MX5 通过Camera.open() 拿到的Camera
*/
@JvmStatic
val isCameraUsable: Boolean
get() {
var canUse = true
var mCamera: Camera? = null
try {
mCamera = Camera.open()
val mParameters = mCamera!!.parameters
mCamera.parameters = mParameters
} catch (e: Exception) {
canUse = false
}
mCamera?.release()
return canUse
}
6.mips64el-linux-android-4.9 系统找不到指定文件
1、是下载老版的ndk把该文件复制到ndk目录下
2、build.gradle中配置
packagingOptions {
doNotStrip '*/mips/*.so'
doNotStrip '*/mips64/*.so'
}
7.EditText如何设置单行显示
设置 android:maxLines="1"
但是这样不行仍然可以换行
再加上一句比较容易忘的 android:inputType="text"
都加上才是单行显示
8.ViewPager内部使用RecyclerView,页面切换导致RecyclerView滑动
抢占焦点的问题
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
9.小米角标是通过通知栏数量进行增加的,如何固定数量
首先先把通知数量清空 然后设置通知栏数量 通知需要手动进行notification通知
if (RomUtils.isXiaomi()) {
//适配小米
//先清除所有角标 在设置角标数量
ShortcutBadger.removeCount(BaseApplication.application.applicationContext)
ShortcutBadger.applyNotification(BaseApplication.application.applicationContext, notification, count)
} else {
ShortcutBadger.applyCount(BaseApplication.application.applicationContext, count)
}
10.如果解决type类型复杂的情况
比如type可以为0文本1图片2视频
可以在实体类中添加方法 isText() isImage() isVideo()
来代替 if语句判断
class Type(val type:Int){
fun isText():Boolean = type == TYPE_TEXT
fun isImage():Boolean = type == TYPE_IMAGE
fun isVideo():Boolean = type == TYPE_VIDEO
}
11.Kotlin循环控制 continue break
// 这里表示表示继续循环
(0..10).forEachIndexed loop@{ index, it ->
println("-- forEach -- ${index} --")
if (it > 5) return@loop
println(it)
}
// 这里表示退出循环
run loop@{
(0..10).forEachIndexed { index, it ->
println("-- forEach -- ${index} --")
if (it > 5) return@loop
println(it)
}
}
12.DialogFragment崩溃Can not perform this action after onSaveInstanceState
//重写DialogFragment的show方法
//可以查看showAllowingStateLoss不过被hide
//通过反射拿到这两个变量进行设置
try {
val mDismissed = DialogFragment::class.java.getDeclaredField("mDismissed")
mDismissed.isAccessible = true
mDismissed.set(this, false)
val mShownByMe = DialogFragment::class.java.getDeclaredField("mShownByMe")
mShownByMe.isAccessible = true
mShownByMe.set(this, true)
manager.beginTransaction()
.add(this, tag)
.commitAllowingStateLoss()
}
} catch (e: Throwable) {
LogUtils.eTag(TAG, e.toString())
}