- 生成类库的jar文件
通常情况下,我们需要把一个类库打包成一个**Jar**文件,而不是**aar**文件,因此我们需要对app.gradle进行修改,如下所示:
task makeJar(type: Copy){
delete 'build/libs/CrashCatcher.jar'
from('build/intermediates/bundles/release/')
into('build/libs')
include('classes.jar')
rename('classes.jar', 'CrashCatcher.jar')
}
makeJar.dependsOn(build)
配置好后,即可通过gradle生成我们想要的jar文件。
- 如何处理Linux不能启用AVD的问题?
First, install some packages and libs:
$ sudo apt-get install lib64stdc++6:i386
$ sudo apt-get install mesa-utils
Second, tweak some links:
$ cd YOURPATH/Android/Sdk/tools/lib64
$ mv libstdc++/ libstdc++.bak
$ ln -s /usr/lib64/libstdc++.so.6 libstdc++
Third, relaunch your AVD device and test it.
3.遇到异常【A problem occurred starting process 'command 'E:\Tools\sdk\ndk-bundle\toolchains\mips64el-linux-android-4.9\prebuilt\windows-x86_64\bin\mips64el-linux-android-strip''】处理办法 , windows下异常
处理办法:修改项目根目录的local.properties文件中ndk.dir的值,
如下,原值是:
ndk.dir=E\:\\Tools\\sdk\\ndk-bundle
修改为:
ndk.dir=E\:\\Tools\\sdk\\ndk-bundle.cmd
再次编辑即可正常,但是可能下次进入项目时还会报一样的错误,同样处理即可!
- 网络安全配置, 有时候我们可能会网络不可访问的时候,可以进行一下配置
在Manifest.xml中的Application节点中配置network_security_config:
android:networkSecurityConfig="@xml/network_security_config"
配置文件(network_security_config.xml)内容如下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
- Android 9.0的WebView打开URL页面,报错:ERR_CLEARTEXT_NOT_PERMITTED
需要在Manifest.xml中的Application节点中配置属性:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:usesCleartextTraffic="true"
...>
...
</application>
</manifest>
- 32位SO库与64位SO库不匹配时,又不能找到64位SO库,只能去掉64位SO库的引用,以免运行时报错,所以做一下处理
android {
........
packagingOptions {
exclude 'lib/arm64-v8a/*'
}
........
}
- 处理Linux系统上出现的/dev/kvm权限问题
当我们想要运行模拟器的时候,出现以上问题,该怎么处理呢?首先我们先查看一下/dev/kvm所在权限组:
ls -l /dev/kvm
我们可能会得到类似于这样的结果:
crw-rw---- 1 root kvm 10, 232 2月 15 09:22 /dev/kvm
就结果而看,我们的/dev/kvm属于root用户的kvm组
怎么把当前用户加入kvm组呢?首先安装一个软件:
sudo apt install qemu-kvm
执行安装完成后,我们添加用户到组
sudo adduser UserName kvm
添加完成后即可,然后重启电脑!
AndroidStudio就开始打开项目了,这个过程会比较缓慢,有时,AS会出现如下信息:
1). 在/etc/sysctl.conf 文件末尾中添加如下代码:
fs.inotify.max_user_watches = 524288
2). 然后在终端执行以下命令:
sudo sysctl -p --system
最后重启AS
- 如何获取手机的存储设备目录
Android N 提供了StorageManager类,并开放了StorageVolume类的部分方法,因此可以使用一下方法可以靠谱的获得相关路径和信息。
10.如何保存文件到手机并同步资源
看示例代码:
/**
* 保存到本地
* @param fileName 文件名
*/
@SuppressLint("Recycle")
private fun saveToLocal(fileName: String, bitmap: Bitmap): Boolean {
try {
var newFileName = fileName
var isOriginalExists = true
val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null,
"${MediaStore.Images.Media.DISPLAY_NAME} like ?", arrayOf(fileName), null)
if (cursor != null && cursor.count > 0) {
if (cursor.moveToNext()) {
isOriginalExists = contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"${MediaStore.Images.Media._ID}=?",
arrayOf(cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID)).toString())) <= 0
}
}
cursor?.close()
if (isOriginalExists) newFileName = "${System.currentTimeMillis()}_$fileName"
val uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ContentValues().apply {
@Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Pictures")
else {
val dir = when (Environment.MEDIA_MOUNTED) {
Environment.getExternalStorageState() ->
Environment.getExternalStorageDirectory().absolutePath
else -> cacheDir.absolutePath
}
put(MediaStore.Images.Media.DATA,
File("${dir}/DCIM/Pictures", newFileName).absolutePath)
}
put(MediaStore.Images.Media.DISPLAY_NAME, newFileName)
put(MediaStore.Images.Media.DESCRIPTION, newFileName)
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
})
if (uri != null) {
val oos = contentResolver.openOutputStream(uri)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, oos)
oos?.flush()
oos?.close()
return true
}
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
11.如何解决错误: android studio 3 字节的 UTF-8 序列的字节 3 无效。(3 �ֽڵ� UTF-8 ���е��ֽ� 3 ��Ч��)?
- 配置IDE file-coding 都为 UTF-8;
- 配置IDE vmOptions 为 -Dfile.encoding=UTF-8;
- 配置 app.gradle:
compileOptions { encoding 'UTF-8' //设置为UTF-8 .... //其他配置 }
12.如何播放本地视频,且不黑屏。 推荐使用TextureView+MediaPlayer+Surface
private var mTexture: TextureView? = null
private var mPlayer: MediaPlayer? = null
private var mSurface: Surface? = null
private var mVideoUri: Uri? = null
private var mListener: OnmPlayerStateChangedListener? = null
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
fun setOnPlayerStateChangedListener(listener: OnmPlayerStateChangedListener) {
this.mListener = listener
}
var videoUri: Uri?
get() = mVideoUri
set(value) {
mVideoUri = value
}
fun initializer(context: Context) {
mTexture = TextureView(context).apply {
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
surfaceTextureListener = this@CustomVideoView
}
addView(mTexture)
}
override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
if (mVideoUri == null)
throw Exception("请首先设置播放源")
mSurface = Surface(surface)
PlayerThread(mVideoUri!!).start()
mListener?.onStarted()
}
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
onReleasemPlayer()
mTexture = null
mSurface = null
return true
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}
fun onReleasemPlayer() {
try {
if (mPlayer != null) {
if (mPlayer?.isPlaying == true)
mPlayer?.pause()
mPlayer?.stop()
mPlayer?.release()
}
mPlayer = null
} catch (e: Exception) {
Log.e("CustomVideoView", e.message)
} finally {
mListener?.onReleased()
}
}
/**
* 使视频适配屏幕
* @param textureWidth Texture宽度
* @param textureHeight Texture高度
*/
private fun stretchingVideoSize(textureWidth: Float, textureHeight: Float) {
val matrix = Matrix()
val videoWidth = mPlayer?.videoWidth ?: return
val videoHeight = mPlayer?.videoHeight ?: return
val scaleX = textureWidth / videoWidth
val scaleY = textureHeight / videoHeight
val originScaleX = videoWidth / textureWidth
val originScaleY = videoHeight / textureHeight
matrix.preScale(originScaleX, originScaleY)
val maxScale = maxOf(scaleX, scaleY)
matrix.preScale(maxScale, maxScale)
mTexture?.setTransform(matrix)
mTexture?.postInvalidate()
}
private inner class PlayerThread(private val uriSource: Uri) : Thread() {
override fun run() {
try {
mPlayer = MediaPlayer().apply {
setDataSource(context, uriSource)
setSurface(mSurface)
setAudioAttributes(
AudioAttributes.Builder()
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
.build()
)
setOnPreparedListener {
it?.start()
if (context is Activity) (context as Activity).runOnUiThread {
val textureWidth =
mTexture?.measuredWidth?.toFloat() ?: return@runOnUiThread
val textureHeight =
mTexture?.measuredHeight?.toFloat() ?: return@runOnUiThread
stretchingVideoSize(textureWidth, textureHeight)
}
}
setOnCompletionListener { mListener?.onCompleted() }
}
mPlayer?.prepare()
} catch (e: Exception) {
Log.e("CustomVideoView", "播放视频失败$e")
}
}
}
- android界面置灰效果实现
val paint = Paint()
val cm = ColorMatrix()
cm.setSaturation(0f)
paint.colorFilter = ColorMatrixColorFilter(cm)
window.decorView.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
- WebView与Native交互,通过js方法获取的Html内容携带unicode字段,如何处理?
Gson().fromJson("html-unicode", String::class.java) //这样能去掉乱码
如果是Flutter又该如何处理?可以考虑在js中把数据URIComponentEncode(), 取出来用时,使用Flutter的Uri.componentDecode().trim(start|end, "")去掉头尾的双引号。
Enjoy yourself !
如果能帮到您,请点赞,谢谢!