Android開發(fā)問題集錦(2023.09.20更新)

  1. 生成類庫的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文件亲铡。
  1. 如何處理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

再次編輯即可正常吆鹤,但是可能下次進入項目時還會報一樣的錯誤厨疙,同樣處理即可!

  1. 網(wǎng)絡安全配置, 有時候我們可能會網(wǎng)絡不可訪問的時候疑务,可以進行一下配置

在Manifest.xml中的Application節(jié)點中配置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>
  1. Android 9.0的WebView打開URL頁面沾凄,報錯:ERR_CLEARTEXT_NOT_PERMITTED

需要在Manifest.xml中的Application節(jié)點中配置屬性:

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        ...
        android:usesCleartextTraffic="true"
        ...>
        ...
    </application>
</manifest>
  1. 32位SO庫與64位SO庫不匹配時梗醇,又不能找到64位SO庫,只能去掉64位SO庫的引用撒蟀,以免運行時報錯叙谨,所以做一下處理
android {
      ........
       packagingOptions {
        exclude 'lib/arm64-v8a/*'
       }
        ........
}
  1. 處理Linux系統(tǒng)上出現(xiàn)的/dev/kvm權限問題

當我們想要運行模擬器的時候,出現(xiàn)以上問題牙肝,該怎么處理呢唉俗?首先我們先查看一下/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

執(zhí)行安裝完成后虫溜,我們添加用戶到組

sudo adduser UserName kvm

添加完成后即可,然后重啟電腦股缸!

  1. AndroidStudio就開始打開項目了,這個過程會比較緩慢,有時,AS會出現(xiàn)如下信息:


    提示信息

1). 在/etc/sysctl.conf 文件末尾中添加如下代碼:

fs.inotify.max_user_watches = 524288

2). 然后在終端執(zhí)行以下命令:

sudo sysctl -p --system

最后重啟AS

  1. 如何獲取手機的存儲設備目錄

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 字節(jié)的 UTF-8 序列的字節(jié) 3 無效瘾境。(3 ???? UTF-8 ???е???? 3 ??Ч??)

  1. 配置IDE file-coding 都為 UTF-8;
  2. 配置IDE vmOptions-Dfile.encoding=UTF-8;
  3. 配置 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")
          }
      }
  }
  1. android界面置灰效果實現(xiàn)
        val paint = Paint()
        val cm = ColorMatrix()
        cm.setSaturation(0f)
        paint.colorFilter = ColorMatrixColorFilter(cm)
        window.decorView.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
  1. WebView與Native交互,通過js方法獲取的Html內容攜帶unicode字段旺入,如何處理兑凿?
Gson().fromJson("html-unicode", String::class.java) //這樣能去掉亂碼

如果是Flutter又該如何處理?可以考慮在js中把數(shù)據(jù)URIComponentEncode(), 取出來用時茵瘾,使用Flutter的Uri.componentDecode().trim(start|end, "")去掉頭尾的雙引號礼华。

Enjoy yourself !

如果能幫到您,請點贊拗秘,謝謝圣絮!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市雕旨,隨后出現(xiàn)的幾起案子扮匠,更是在濱河造成了極大的恐慌,老刑警劉巖凡涩,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件餐禁,死亡現(xiàn)場離奇詭異,居然都是意外死亡突照,警方通過查閱死者的電腦和手機帮非,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人末盔,你說我怎么就攤上這事筑舅。” “怎么了陨舱?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵翠拣,是天一觀的道長。 經(jīng)常有香客問我游盲,道長误墓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任益缎,我火速辦了婚禮谜慌,結果婚禮上,老公的妹妹穿的比我還像新娘莺奔。我一直安慰自己欣范,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布令哟。 她就那樣靜靜地躺著恼琼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屏富。 梳的紋絲不亂的頭發(fā)上晴竞,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音狠半,去河邊找鬼颓鲜。 笑死,一個胖子當著我的面吹牛典予,可吹牛的內容都是我干的。 我是一名探鬼主播乐严,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瘤袖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昂验?” 一聲冷哼從身側響起捂敌,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎既琴,沒想到半個月后占婉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡甫恩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年逆济,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡奖慌,死狀恐怖抛虫,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情简僧,我是刑警寧澤建椰,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站岛马,受9級特大地震影響棉姐,放射性物質發(fā)生泄漏。R本人自食惡果不足惜啦逆,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一伞矩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹦浦,春花似錦扭吁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至溉贿,卻和暖如春枫吧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宇色。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工九杂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宣蠕。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓例隆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抢蚀。 傳聞我的和親對象是個殘疾皇子镀层,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容