Android開發中遇到的bug
1、將Eclipse專案匯入到Android studio 中 很多點9圖出現問題解決方法
在build.gradle裡新增以下兩句:
aaptOptions.cruncherEnabled = false
aaptOptions.useNewCruncher = false
用來關閉Android Studio的PNG合法性檢查的,直接不讓它檢查。
2、Android Studio 錯誤: 非法字元: ‘\ufeff’
原因:Eclipse可以智慧的把UTF-8+BOM檔案轉為普通的UTF-8檔案,Android Studio還沒有這個功能,所以使用Android Studio編譯UTF-8+BOM編碼的檔案時會出現”非法字元:’\ufeff’”之類的錯誤
手動將UTF-8+BOM編碼的檔案轉為普通的UTF-8檔案。
用EdItPlus開啟.java檔案依次:文件 -> 文字編輯 -> 轉換文字編碼 -> 選擇UTF-8編碼即可
3、將專案匯入到AS中出現以下問題
Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
解決方法:在build.grade中新增以下程式碼
android{
packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
}
}
4、Timeout waiting to lock cp_proj class cache for build file
Error:Timeout waiting to lock cp_proj class cache for build file '/Users/Mr.xiao/Desktop/AndroidShopNC2014MoblieNew/androidShopNC2014Moblie/build.gradle'
(/Users/Mr.xiao/.gradle/caches/2.10/scripts/build_3cyr7hzjurcc62ge3ixidshos/cp_proj).
It is currently in use by another Gradle instance.
Owner PID: unknown
Our PID: 1412
Owner Operation: unknown
Our operation: Initialize cache
Lock file: /Users/Mr.xiao/.gradle/caches/2.10/scripts/build_3cyr7hzjurcc62ge3ixidshos/cp_proj/cache.properties.lock
解決方案,以上是錯誤提示
解決的思路很簡單隻需要把cache.properties.lock檔案刪除了就可以了。當時我們刪除的時候會被佔用這時候需要進入工作管理員結束關於java的程序就行比如 java 的jdk 刪除後重啟讓java jdk啟動 啟動Android Studio就能啟動APK了
5、修改了Android專案的最小SDK版本之後出現很多stysle檔案找不到
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "net.mmloo2014.android"
minSdkVersion 14
targetSdkVersion 23
}
compileSdkVersion 是多少版本的
那麼compile ‘com.android.support:appcompat-v7:23.2.1’ 就是啥版本的
6、Android studio 編譯問題:finished with non-zero exit value 2
問題描述
Error:Execution failed for task ':androidShopNC2014Moblie:transformClassesWithDexForDebug'.
com.android.build.api.transform.TransformException:
com.android.ide.common.process.ProcessException:
java.util.concurrent.ExecutionException:
com.android.ide.common.process.ProcessException:
org.gradle.process.internal.ExecException:
Process 'command '/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java'' finished with non-zero exit value 2
解決方案:這個錯誤在app的build.gradle裡面新增下面這句就好了
android {
defaultConfig {
multiDexEnabled true
}
}
65536問題
7、Android studio 編譯問題:finished with non-zero exit value 1
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
com.[Android]([url=http://lib.csdn.net/base/15]http://lib.csdn.net/base/15[/url])
.build.api.transform.TransformException:
com.android.ide.common.process.ProcessException:
org.gradle.process.internal.ExecException:
Process 'command 'F:\Program Files (x86)\[Java]([url=http://lib.csdn.net/base/17]
http://lib.csdn.net/base/17[/url])\jdk1.8.0_31\bin\java.exe''
finished with non-zero exit value 1
由於匯入的依賴出現重複造成的,解決方案:
這個是因為依賴包重複了 (像v4和nineoldandroids),app中實現了對easeUI的依賴,但是app和easeUI都添加了對這個包的依賴。所以就報這個錯誤,修改之後再報,就clean,rebuild一下
8、transformClassesWithJarMergingForDebug
Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'.
> com.android.build.api.transform.TransformException:
java.util.zip.ZipException:duplicate entry: org/apache/http/ConnectionClosedException.class
解決方案
這個是在我們啟動的時候報錯的,而不是在編譯的時候,原因是這樣的,報這個錯是因為有2個庫中存在相同的類。大家可以看到stackoverflow上有人也提了這樣的問題。只需要刪除其中的一個就可以解決了
9、新增第三方依賴出現的問題processDebugManifest
Error:Execution failed for task ':app:processDebugManifest'.
Manifest merger failed :
uses-sdk:minSdkVersion 14 cannot be smaller than version 19 declared in library [com.github.meikoz:basic:2.0.3]
/AndroidStudioCode/EnjoyLife/app/build/intermediates/exploded-aar/
com.github.meikoz/basic/2.0.3/AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.android.core" to force usage
錯誤原因:
出現這個錯誤的原因是我引入的第三方庫最低支援版本高於我的專案的最低支援版本,異常中的資訊顯示:我的專案的最低支援版本為14,而第三方庫的最低支援版本為19,所以丟擲了這個異常。
解決方案:在AndroidManifest.xml檔案中標籤中新增
<uses-sdk tools:overridelibrary="xxx.xxx.xxx"></uses-sdk>
其中的xxx.xxx.xxx為第三方庫包名,如果存在多個庫有此異常,則用逗號分割它們
這樣做是為了專案中的AndroidManifest.xml和第三方庫的AndroidManifest.xml合併時可以忽略最低版本限制
10、Android studio 編譯問題:finished with non-zero exit value 1
錯誤描述
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.ide.common.process.ProcessException:
org.gradle.process.internal.ExecException:
Process 'command '/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
錯誤原因
buildToolsVersion版本太高,我原來的 buildToolsVersion “24.0.0” 需要jdk1.8,而我的是jdk1.7,所以一直報這個錯,剛開始以為是v4包和V7包衝突,因為之前遇到這樣的問題,而這次刪除V4包之後依然報這個錯,上stackoverflow搜了一下,把buildTools版本降下來就好了。
解決方案
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
}
11、Android studio 編譯問題:Gradle DSL not found ‘android()’
解決方案 配置build.gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
}
}
allprojects {
repositories {
jcenter()
}
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
}
}
allprojects {
repositories {
jcenter()
}
}
配置app/build.gradle:
apply plugin: 'com.android.application'android {
compileSdkVersion 23
buildToolsVersion '23.0.3'
defaultConfig {
minSdkVersion 9
targetSdkVersion 23
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.2.1'
}
最後再同步一下sync即可
12、Android studio 編譯問題:Gradle DSL not found ‘android()’
Error:(51, 52) 錯誤: -source 1.6 中不支援 diamond 運算子
(請使用 -source 7 或更高版本以啟用 diamond 運算子)
解決方法,在build gradle中進行配置如下程式碼
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
最後同步一下即可
13、Glide使用問題:使用Glide載入圓角圖片,第一次顯示佔位圖
問題描述
最近在專案中使用Glide載入圓形圖片,並且設定placehloder和error兩個佔位圖,執行發現,第一次載入圖片只顯示佔位圖,需要第二次進入的時候才會正常顯示。
如果你剛好使用了這個圓形Imageview庫或者其他的一些自定義的圓形Imageview,而你又剛好設定了佔位的話,那麼,你就會遇到第一個問題。如何解決呢?
方案一:不設定佔位圖
方案二:使用Glide的Transformation API自定義圓形Bitmap的轉換
/**
* Glide圓形圖片處理
*/
static class CircleTransform extends BitmapTransformation {
public CircleTransform(Context context) {
super(context);
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return circleCrop(pool, toTransform);
}
private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.RGB_565);
if (result == null) {
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
return result;
}
@Override
public String getId() {
return getClass().getName();
}
}
使用方法:
Glide.with(context)
.load(imageUrl)
.placeholder(placeholder)
.error(errorImage)
.transform(new CircleTransform(context))
.into(imageView);
方案三:重寫Glide的圖片載入監聽方法,具體如下
Glide.with(mContext)
.load(url)
.placeholder(R.drawable.loading_drawable)
.into(new SimpleTarget<bitmap>(width, height) {
@Override public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
// setImageBitmap(bitmap) on CircleImageView
}
});
注意事項:該方法在listview上覆用有問題的bug,如果在listview中載入CircleImageView,請不要使用該方法
方案四:不使用Glide的預設動畫:
Glide.with(mContext)
.load(url)
.dontAnimate()
.placeholder(R.drawable.loading_drawable)
.into(circleImageview);
14、json資料解析問題:json串頭部出現字元:”\ufeff” 解決方法
異常資訊
org.json.JSONException: Value ? of type java.lang.String cannot be converted to JSONObject
解析伺服器返回 的json格式資料時,我們可能會發現,資料格式上是沒有問題的,但是仔細對比會發現,在json串頭部發現字元:”\ufeff”
客戶端解決方案:
/**
* 異常資訊:org.json.JSONException: Value ? of type java.lang.String cannot be converted to JSONObject
* json串頭部出現字元:"\ufeff" 解決方法
* @param data
* @return
*/
public static final String removeBOM(String data) {
if (TextUtils.isEmpty(data)) {
return data;
}
if (data.startsWith("\ufeff")) {
return data.substring(1);
}
else {
return data;
}
}
伺服器端解決方案:
將輸出此json的php原始碼重新用editplus之類用utf-8無BOM的編碼儲存。不要用windows系統自帶的記事本編輯php原始碼,這個BOM就是記事本這些windows自帶的編輯器引入的
15、Android studio編譯問題:not found ndk()
解決方案
出現該問題,可能是由於ndk配置在build.gradle配置檔案中位置弄錯導致的
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.guitarv.www.ndktest"
minSdkVersion 17
targetSdkVersion 23
versionCode 1
versionName "1.0"
ndk {
moduleName = "HelloJNI"
}
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir "src/main/libs"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
16、compileDebugJavaWithJavac
Error:Execution failed for task ':compileDebugJavaWithJavac'
17、Not recognizing known sRGB profile that has been edited
AAPT err(Facade for 1975606064):
E:\workspace\SmartCity\app\src\main\res\mipmap-hdpi\bottom_tab_bg.png:
libpng warning: iCCP:
Not recognizing known sRGB profile that has been edited
在build.gradle裡新增以下兩句:aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false,就直接新增到buildToolsVersion的下方即可,這個是用來關閉Android Studio的PNG合法性檢查的,直接不讓它檢查
18、app:mergeDebugResources
Error:Execution failed for task ':app:mergeDebugResources'
19、transformClassesWithDexForDebug
Error:Execution failed for task ':demo:transformClassesWithDexForDebug'
20、gradle dsl method not found “runProguard()”
原因:gradle版本更新,方法名改變,改為minifyEnable()
21、the specified child already has a parent , you must call removeview() on the child’s parent first
Fragment重複載入的問題:一個孩子只能有一個爸爸
解決方案:在新增Fragment到ViewPager之前,先判斷Fragment是否已經新增到ViewPager了,如果已經新增,先remove後再新增
public static void removeSelfFromParent(View view) {
if (view != null) {
ViewParent parent = view.getParent();
if (parent != null && parent instanceof ViewGroup) {
ViewGroup group = (ViewGroup) parent;
group.removeView(view);
}
}
}
22、illegalstateException非法狀態異常
23、NullPointException 空指標異常
24、you need tou use a theme.appcompat theme to with activity,Error inflating class android.support.design.widget.TabLayout
使用TabLayout的時候出現該問題,給Activity設定一個theme.appcompat 主題,例如
android:theme="@style/Theme.AppCompat.Light"
25、fragment中巢狀viewpager,vierpager中有多個fragment,不顯示
將getSupportFragmentManager()改為getChildFragmentManager()
26、Error:Failed to resolve: com.android.support:support-core-utils:24.2.1
在使用Fresco的時候報的錯,升級Android Support Library就好了,原因是Android Support Library升級後v4包拆分成了好幾個小包,其中就有support-core-utils
27、Rendering Problems
Failed to load the LayoutLib: com/android/layoutlib/bridge/Bridge : Unsupported major.minor version 52.0 (Details)
這是由於在Android 7.0 版本中增加對JAVA8的支援,所以在此給出兩種中解決辦法:
改下Android version或安裝jdk1.8
28、Suspending all threads took: 5.639ms
29、ImageView no longer exists. You should not use this PhotoViewAttacher any more
30、java.lang.IllegalArgumentException: pointerIndex out of range
在使用ViewPager展示圖片的時候,使用了PhotoView對ImageView進行多點觸控放大縮小,出現了java.lang.IllegalArgumentException: pointerIndex out of range
31、com.google.gson.JsonSyntaxException: java.io.EOFException: End of input at line 1 column 2 path
T t = gson.fromJson(gsonString,type);
32、Package manager has died
33、android java.net.UnknownHostException: Unable to resolve host “…”: No address associated 錯誤
我們在android開發的時候經常會遇到這個錯誤,一般來說,造成這種錯誤的最普遍情況有兩種:
1、android裝置網路連線沒開啟,例如3G網路和WIFI網路
所以,如果遇到這種錯誤時,請先檢視網路是否已正常連線.
2、Manifest檔案沒有標明網路訪問許可權
如果確認網路已經正常連線並且還是出這種錯誤的話,那麼請看下你的Manifest檔案是否標明應用需要網路訪問許可權,如果沒標明的話,也訪問不了網路,也會造成這種情況的
<uses-permission android:name="android.permission.INTERNET"/>
Failed to install *.apk on device ‘emulator-5554’: timeout
錯誤提示:
Failed to install helloworld.apk on device ‘emulator-5554’: timeout
或者the user data image is used
原因:由於模擬器已經開啟而沒有關閉或者非法關閉引起的。
解決方法:
刪除 C:Documents and SettingsAdministrator.androidavd對應版本.avd
下所有以.lock結尾的資料夾。
或者
Failed to install .apk on device :
timeout Launch canceled!
還有一種辦法:
在window->preferences->Android->DDMS->ADB connection time out (ms):
將這個值設定的大一些,預設為5000,設定成500000,然後就OK了
Android adb常見問題整理
問題1
The connection to adb is down, and a severe error has occured.
You must restart adb and Eclipse.
Please ensure that adb is correctly located at ‘adb.exe’ and can be executed.
解決方法
adb kill-server
adb start-server
問題2
ADB server didn’t ACK
failed to start daemon
解決方法
DDMS - Devices - Reset adb
如果不行,關閉豌豆莢或者Eclipse重啟
問題3
Adb failed to restart! Make sure the plugin is properly configured
解決方法
殺死 Wandoujia 相關的所有程序,ok
wandoujia_daemon.exe
wandoujia_helper.exe
AndroidStudio 建議升級此編譯器,主版本 52 比 51 新, 此編譯器支援最新的主版本
JDK導致的問題
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
上面表示編譯的時候使用Android 24的版本編譯,最高支援到版本24
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
這兩行表示依賴了24版本的兩個包
解決方法:
1、我的JDK是1.7,將JDK升級到1.8之後應該可以解決這個問題(這個只提供參考,因為公司還有其他專案,所以我沒有升級到JDK1.8,但是同事是1.8執行正常)
2、將上面程式碼的24版本統統改為23版本,targetSdkVersion 24這個也要改為23,如果不改的話引入的兩個包會報紅,同時依賴的包也改為下面
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:design:23.2.1'
debug.keystore not found for signing config ‘debug’
UnspportedOperationException
java.util.AbstractList.remove
List<String> mOtherChannel = Arrays.asList(CommonUtil.getStringArr(R.array.otherchannel));
mOtherChannel.remove("xxx");
UnspportedOperationException丟擲的原因是使用了不當的容器操作。通常是由於嘗試修改固定長度的容器的緣故,呼叫Array.asList() 方法會返回這種容器。因為陣列顯然是固定長度的容器,使用asList方法轉換為list也會保持這種屬性。
Array.asList()返回的是Arrays類內部自定義的AbstractList的子類,它沒有實現remove方法。
List<String> mOtherChannel = new ArrayList<>(Arrays.asList(CommonUtil.getStringArr(R.array.otherchannel)));
The application’s PagerAdapter changed the adapter’s contents without calling PagerAdapter#notifyDataSetChanged
今天開發的時候遇到如題所述的異常,找了一下在satckoverflow上看到一個比較靠譜的答案:
After ADT 22 the PagerAdapter has gotten very strict about calling notifyDataSetChanged() before calling getCount(). It evidently keeps track of what it thinks the count should be and if this is not the same as what getCount() returns it throws this exception. So the solution is simply to call notifyDataSetChanged() on the adapter every time the size of the data changes.
在adt22之後,PagerAdapter對於notifyDataSetChanged()和getCount()的執行順序是非常嚴格的,系統跟蹤count的值,如果這個值和getCount返回的值不一致,就會丟擲這個異常。所以為了保證getCount總是返回一個正確的值,那麼在初始化ViewPager時,應先給Adapter初始化內容後再將該adapter傳給ViewPager,如果不這樣處理,在更新adapter的內容後,應該呼叫一下adapter的notifyDataSetChanged方法。
在初始化ViewPager時,應先給Adapter初始化內容後再將該adapter傳給ViewPager,如果不這樣處理,在更新adapter的內容後,應該呼叫一下adapter的notifyDataSetChanged方法,否則在ADT22以上使用會報The application’s PagerAdapter changed the adapter’s contents without calling PagerAdapter#notifyDataSetChanged的異常,具體原因可參考:http://stackoverflow.com/questions/16756131/fragmentstatepageradapter-stopped-working-after-updating-to-adt-22
java.lang.NoSuchMethodException: getPackageSizeInfo
Field can be converted to a local varible
This inspection searches for redundant class fields that can be replaced with local variables,if all local usages of a field are preceded by assignments to that field,the field can be removed and its usages replaced with local variables.
檢測到這個變數可以使用區域性變數替換,建議刪除並寫成區域性變數
解決方案:刪除private XXX XXX; 這句,並在使用的地方直接宣告和例項化
Failed to resolve attribute at index 6
View view = View.inflate(getApplicationContext(), R.layout.activity_detail, null);
與UI相關的要使用Activity上下文,而不是ApplicationContext
View view = View.inflate(MainActivity.this, R.layout.activity_detail, null);
java.lang.UnsatisfiedLinkError
專案中使用sqlcipher加密資料庫,使用了so庫,模擬器執行的時候報錯,換成真機沒有問題,模擬器是x86架構的,換成ARM架構的應該沒有問題
導致產生unsatisfiedlink的幾個原因
1. 相關資訊
hyphenatechatsdk提供的指令集型別僅提供armeabi, arm64-v8a, x86三種,這裡需要解釋一下相關資訊。
armeabi和armeabi-v7a是相近似的指令集,v7a是增強型指令集,執行速度,效率均有所提高,他們都是32位指令,並且相容。
arm64-v8a對應arm 64位指令集,arm的64位策略和intel IA32不一樣,intel的64位指令是相容32位指令,32位指令編譯的程式可以直接在64位機器上執行。
但是arm不是,arm64位和arm32位是彼此獨立的指令系統,不相容。arm這樣設計的原因是因為執行在嵌入式上,設計指標更趨向於效率,和耗電考量。
實際上arm64位晶片上同時包含著64指令處理器,和32位指令處理器,只不過兩個處理器彼此獨立。
2. 影響連結的限制條件
armeabi的so實際上可以執行在64位機器上,只不過google增加了限制條件。
- Android4.x, 只要能找到so,就可以執行,so可以在armeabi,armeabi-v7a, arm64-v8a,so位置可以很隨意。
Android5.x開始,檢查更加嚴格,會只有和晶片型號對應目錄的so會安裝到手機中。
舉個例子,開發環境下目錄結構如下
libs/armeabi/: libhyphenate.so libhyphenate_av.so
libs/armeabi-v7a: libmediadata.so
手機對應的指令集是armeabi-v7a,之中安裝到手機的只有libmediadata.soAndroid6.x下,檢查更加嚴格。有一條規則,之前測試又遇到,現在不太確認。
libs/armeabi/: libhyphenate.so libhyphenate_av.so。
libs/arm64-v8a (沒有此目錄)。
在64位機器上也可以執行。
但是作為開發者通常會依賴其他開發包,比如baiduMap,也會用其他so,不能讓所有開發者都刪掉libs/arm64-v8a的目錄。
不過開發者可以嘗試下刪除arm64-v8a,只留armeabi,這樣安裝包會很小,在各個平臺上也能執行。google考量點是執行速率,更流暢的使用者體驗,作為開發者。服務提供者,我們希望apk儘可能小,對執行速度要求不高。armeabi和armeabi-v7a可以互換,現在市面上的手機很少有armeabi的,基本上是armeabi-v7a,或者64位的高階機器。
檢視手機晶片型號: cat /proc/cpuinfo, 仔細看一下列印資訊,能夠看明白手機指令集,是32位還是64位。
x86目錄,通常對應虛擬機器,很多開發者喜歡在genymotion上開發除錯,這個就對應x86. x86和前面說的intel IA32是一回事,所以只提供32位的,也能在x86-64位機器上執行。
我們的so還依賴於libsqlite.so,不過由於這個包從來沒有變化,使用的是系統預設提供的(/system/lib/)。在Android 6.x及以下的平臺可以執行。
Android7.x執行更嚴格的安全檢查,禁止使用系統目錄的內容。所以如果希望在7.x以上版本,需要把系統目錄的libsqlite.so拷貝出來,也放在自己app對應指令目錄下。
由於目前Android7.x市面上沒有機型,所以目前不在考慮範圍。目前微信…等大app都不能在7.x上執行。mips指令集的手機很少見,聽說聯想有出過,沒見過。
libs/armeabi/libhyphenate.so 和libs.without.audio/armeabi/libhyphenate.so是不同,libs/armeabi/libhyphenate.sos會依賴於libs/armeabi/libhyphenate_av.so,如果找不到會報java.lang.UnsatisfiedLinkError.
not allowed to send broadcast android.intent.action.MEDIA_MOUNTED
當我們儲存圖片後就會發個通知告訴系統讓sdcard重新掛載,這樣其他程式就會立即找到這張圖片。
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
但是到了Android4.4就不靈了,Google將MEDIA_MOUNTED的許可權提高了,於是就報了一個下面的錯誤。
W/System.err﹕java.lang.SecurityException: Permission Denial:
not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from pid=18338, uid=10087
在stackoverfollow中找到了一個辦法,在高版本中使用ACTION_MEDIA_SCANNER_SCAN_FILE去通知系統重新掃描檔案。程式碼如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(mPhotoFile); //out is your output file
mediaScanIntent.setData(contentUri);
CameraActivity.this.sendBroadcast(mediaScanIntent);
} else {
sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
}
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}