接口回调传递参数丢失问题
原因:
此方法需要json数据和bean属性一一对应
JsonObject bsqJson = new JsonParser().parse(commonModel.getJsonData().toString()).getAsJsonObject();
BsqBaseInfoModel bsqModel = new Gson().fromJson(bsqJson, BsqBaseInfoModel.class);
此方法不需json数据和bean属性一一对应
List result=new Gson().fromJson(commonModel.getJsonData().toString(), new TypeToken>(){}.getType());
包:
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
"$ref"
的问题问题:对象转json字符串,断点取到json字符串中带"$ref"
等字样,不是实际的值的问题。(有出现debug正常,release异常的情况)
解决:升级了fastjson版本导致的,使用Gson解析方式。
Gson gson = new Gson();
String idsStr = gson.toJson(submitBean);
现象:报错Can't create handler inside thread that has not called Looper.prepare()
原因:在子线程中new Handler(加Toast也有这个问题)导致的
分析:因为Handler与其调用者在同一线程中,Handler中执行了延迟操作,会导致调用的线程阻塞。每个Hander对象都会绑定一个Looper对象,每个Looper对象对应一个消息队列(MessageQueue),若在创建Handler时不指定与其绑定的Looper对象则默认将当前线程的Looper绑定到该Handler上。
在主线程中直接使用new Hanlder()创建Handler对象,其将自动与主线程的Looper对象绑定;在子线程中直接new创建会报错,因为子线程中没有开启Looper,而Handler对象必须绑定Looper对象。
解决:
方案一:需先在该子线程中手动开启Looper(Looper.prepare()-->Looper.loop()
),然后将其绑定到Handler对象上。
final Runnable runnable = new Runnable(){
@Override
public void run(){
//执行耗时操作
try{
Log.e("bm", "runnable线程:"+ Thread.currentThread().getId() + " name:" + Thread.currentThread().getName());
Thread.sleep(2000L);
Log.e("bm", "执行完耗时操作了~");
} catch (InterruptedException e){
e.printStackTrace();
}
}
};
new Thread(){
public void run(){
Looper.prepare();
new Handler().post(runnable);//在子线程中直接去new一个handler
Looper.loop();//这种情况下,Runnable对象时运行在子线程中的,可以进行耗时操作,但是不能更新UI
}
}.start();
方案二:通过Looper.getMainLooper()
,获得主线程的Looper,将其绑定到此Handler对象上。
final Runnable runnable = new Runnable() {
@Override
public void run() {
//执行耗时操作
try {
Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
Thread.sleep(2000);
Log.e("bm", "执行完耗时操作了~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread() {
public void run() {
new Handler(Looper.getMainLooper()).post(runnable);//在子线程中直接去new 一个handler
//这种情况下,Runnable对象是运行在主线程中的,不可以进行联网操作,但是可以更新UI
}
}.start();
原文链接
背景:
在移动端发现一个用户无法登陆的 bug,经排查,发现是不规范的 Sql 语句以及没做 SQL 攻击的防止导致的。
出现的原因及分析
大多数情况下,我们不需要考虑移动端 SQL 攻击,因为 Android SDK提供的 query/insert/update/delete 等 API 是安全的,但是execSql 这个 API 却不是安全的,尽量别使用这个 API
由于我们的代码,原先的数据存储是靠C++的sqlite,而没借助Android的Sdk来做的。因此,原先一些SQL可能存在问题。
例子
String userName = "";
int age = 24;
mDBHelper.getWritableDatabase().execSQL(String.format(Locale.getDefault(),"insert into " + UserDBHelper.TABLE_NAME+ " (UserName,Age) values(%s,%d)",userName,age));
类似上面的代码,我想 大家的项目里或许也有。看上去,这个没有任何问题,但是却存在sql攻击,当我把userName这个字符串的内容换成,带特殊字符的,如 guolei’ 的时候,这个拼接出来的sql语句就有问题了,回报如下错误。
Process: com.guolei.sqlinsert, PID: 22520
android.database.sqlite.SQLiteException: unrecognized token: "',24)" (code 1): , while compiling: insert into user (UserName,Age) values(error',24)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
这是因为单引号 ‘ 使sql语句发生了截断,在sql语句中,要用连续两个单引号去表达一个单引号字符。这仅仅是一个例子。有兴趣的,大家去了解SQL攻击相关的东西吧。
使用BroadcastReceiver组件需要动态注册或者静态注册,如果动态注册广播,即在代码中使用registerReceiver()方法注册BroadcastReceiver,只有当registerReceiver()的代码执行到了才进行注册,取消时则调用unregisterReceiver()方法。但registerReceiver()方法注册的BroadcastReceiver是全局的并且默认可导出的,如果没有限制访问权限,可以被任意外部APP访问,向其传递Intent来执行特定的功能。因此,动态注册的BroadcastReceive可能会导致拒绝服务攻击、APP数据泄漏或是越权调用等安全风险。
解决方案
1:在 AndroidManifest.xml 文件中使用静态注册 BroadcastReceiver,同时设置 exported=“false”。(关于这个属性后面会说)
2:必须动态注册 BroadcastReceiver时,使用registerReceiver(BroadcastReceiver,IntentFilter,broadcastPermission,android.os.Handle)函数注册。
3:Android8.0新特性想要支持静态广播、需要添加intent.setComponent(new ComponentName()),详情可以自行查阅。
Activity、Service、Provider、Receiver四大组件若配置为android:exported =”true”,将可以被外部应用调用,这样存在安全隐患的风险。
解决方案
在应用的AndroidManifest.xml文件中,设置组件的android:exported 属性为false或者通过设置自定义权限来限制对这些组件的访问。值得一提的是,若部分功能使用前提是配置必须使用exported为true,这种情况开发者应该根据实际情况来进行集成。
这个只有在hide,show的时候会触发 在add 的时候是不会触发的 首次加载的时候是不触发的onHiddenChanged
activity 上有4个fragment 当前的fragment 为A activity finish掉的时候, B fragment不走生命周期的 除非是已经被调用.add的时候才会走生命周期
onHiddenOnChange()+onResume()的区别:
第一次可见的时候生命周期都是onHiddenOnChange–>onResume
其它都只走onHiddenOnChange。除非是activity切换了走了生命周期,这个时候会走onPause跟onResume但是不走onHiddenOnChange
//在 activity 的 onCreate 中
mFragmentManager.beginTransaction()
.add(resId, new OneFragment())
//这里会报异常,activity has been destroyed
.commit();
原因:Fragmenttransaction也是在 onCreate 中初始化,也许是异步初始化。这就涉及到执行顺序问题。
解决:add(redId,Fragment)放到onCreate()后的生命周期onResume()
java.lang.RuntimeException: Unable to start activity ComponentInfo{}java.lang.IllegalStateException: Activity has been destroyed
Caused by: java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1560)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:696)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:662)
fragment = new OneFragment();
mFragmentManager.beginTransaction()
.add(com.handsomeyang.mango.R.id.root_relative_layout, fragment)
//这里会报异常,activity has been destroyed
.commit();
当我在Activity 的onCreate 中初始化fragment 并且用事务添加到Activity 的时候报错,说是Activity 已被销毁,然而怎么也不能理解,commit 源码点进去没找到,百度了好一会,在stackoverflow 上一个出现类似问题的评论中发现一句话: 说是Fragmentranscation 也是在onCrate中初始化的,也许是异步初始化,这样就涉及到代码执行顺序问题,最好把addFragment 往后提一提,我把这段同样的代码写在OnResume中就能顺利添加上fragment 并且不报错了。
失败原因:应用组件的命名与已安装应用有冲突
可能是包名问题(已安装 app 有相同包名)
解决:需要重新定一个包名,同时在相关第三方平台上要改掉包名
可能是provider的authorities问题(已安装的 app 有相同的 authorities)
解决:正在安装的 app 的 authorities 改另一个名称(随便改,可以带上 applicationId)
/**
* @param path下载地址
* @param filePath存储路径
* @param progressDialog进度条
* @return
* @throws Exception
*/
public static File getFile(String path,String filePath,ProgressDialog progressDialog) throws Exception{
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(2000);
connection.setRequestMethod("GET");
if(connection.getResponseCode() == 200){
int total = connection.getContentLength();
progressDialog.setMax(total);
InputStream is = connection.getInputStream();//获得socket输入流
File file = new File(filePath);
FileOutputStream fos = new FileOutputStream(file);//file输出流
byte[] buffer = new byte[1024];
int len;
int progress = 0;
while((len = is.read(buffer)) != -1){
fos.write(buffer);
progress += len;
progressDialog.setProgress(progress);
}
fos.flush();
is.close();
fos.close();
connection.disconnect();
return file;
}
return null;
}
解决:
byte[] buffer = new byte[1024];
这行代码,把1024改成了128,又改成了64,结果就没问题了。
解决:在安装完毕后加 return
// 安装apk
private void installApk(File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".updateProvider", file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
//兼容8.0-26
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AppUtils.installApp(file, BuildConfig.APPLICATION_ID + ".updateProvider");
//兼容8.0以上的安装完毕需要加return,否则有安装成功但是弹出“解析包失败”的页面来误导用户
return;
}
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
activity.startActivityForResult(intent, 999);
}
低版本的blankj.utilcode(如"com.blankj:utilcode:1.10.0")需要在App.java中添加初始化操作。
在升级页面VersionUpgradePresenter.java
的安装apk逻辑中添加
//兼容8.0 (API26)
if(Build.VERSION.SDDK_INT > Build.VERSION_CODES.N){
AppUtils.installApp(file, BuildConfig.APPLICATION_ID + ".updateProvider");
}
完整安装apk的代码:
protected void installApk(File file) {
//这是在 com.blankj:utilcode:1.10.0版本下的处理方式
// Intent intent = new Intent(Intent.ACTION_VIEW);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".updateProvider", file);
// intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
// // 兼容8.0-26---新增兼容代码,里面使用到了BlankJ的工具类库
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// AppUtils.installApp(file, BuildConfig.APPLICATION_ID + ".updateProvider");
// }
// } else {
// intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// }
// startActivityForResult(intent, INSTALL_DG_APP_REQUEST_CODE);
//在高版本 com.blankj:utilcode:1.23.4以上直接用以下语句即可
AppUtils.installApp(this,file,INSTALL_DG_APP_REQUEST_CODE);
}
问题:AS打包卡在app:transformClassesAndResourcesWithR8ForRelease
卡在app:transformClassesAndResourcesWithR8ForRelease
很长时间一直不能生成包,有时候产生java.lang.OutOfMemoryError: GC overhead limit exceeded
错误。而且编译打包时偶尔会报Error:java.lang.OutOfMemoryError
解决(在 gradle.properties
中添加):
# 编译时使用守护进程
org.gradle.daemon=true
#JVM 最大允许分配的堆内存,按需分配
org.gradle.jvmargs=-Xmx16896m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# 使用并行编译
org.gradle.parallel=true
org.gradle.configureondemand=true
#启用新一代Dex编译器D8
android.enableD8=true
#启用gradle缓存
org.gradle.caching=true
运行时报警告:
WARNING: The following project options are deprecated and have been removed:
android.enableAapt2
This property has no effect, AAPT2 is now always used.
解决方案:
移除gradle.properties
中android.enableAapt2=true
java.lang.VerifyError: Verifier rejected class d.w.b.f.a: java.lang.String d.w.b.f.a.a(java.lang.String) failed to verify: java.lang.String d.w.b.f.a.a(java.lang.String): [0x36] 'this' argument 'Precise Reference: org.apache.commons.codec.binary.Base64' not instance of 'Reference: org.apache.commons.codec.binary.BaseNCodec' (declaration of 'd.w.b.f.a' appears in /data/app/xxx.xxx.yyldy-naDf47h1LBlsvDDqMvd1rw==/base.apk!classes3.dex)
at d.w.b.f.a.a(AESHelper.java:39)
at d.w.b.b.b.a(RemoteClient.java:119)
at b.a.b.a.b(RequestApi.java:2739)
at b.a.i.a.k.b(IsExistIMAccount.java:58)
at xxx.xxx.view.login.WelcomeActivity.onCreate(WelcomeActivity.java:95)
at android.app.Activity.performCreate(Activity.java:7458)
at android.app.Activity.performCreate(Activity.java:7448)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1286)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3409)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3614)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:86)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
at android.os.Handler.dispatchMessage(Handler.java:112)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
解决:
public static String AESEncrypt(String plainText) {
String encryptedValue = null;
try {
Key key = new SecretKeySpec(keyWord.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
byte[] byteContent = plainText.getBytes("utf-8");
try {
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(_key1));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
byte[] encValue = cipher.doFinal(byteContent);
//把上面这句注释掉,改成底下那句
//encryptedValue = new String(new Base64().encode(encValue));
encryptedValue = new String(Base64.encodeBase64(encValue));
} catch (Exception e) {
e.printStackTrace();
}
return encryptedValue;
}
遇到的类ShoppingCartFragment类
/**
* 构建选中的id集合,用于获取购物车商品及提交结算时验证使用
*/
private String generateSelectIdList(NewShoppingCartBean bean) {
if (bean != null) {
ItemCartIds itemCartIds = new ItemCartIds();
List<ItemCartIds.ItemCartId> idList = new ArrayList<>();
for (NewShoppingCartBean.ShoppingCartBean shoppingCartBean : bean.getShoppingCartList()) {
for (NewShoppingCartBean.ShoppingCartBean.CartActivityItemBean cartActivityItemBean : shoppingCartBean.getCartActivityItemList()) {
for (NewShoppingCartBean.ShoppingCartBean.CartActivityItemBean.CartItemBean cartItemBean : cartActivityItemBean.getCartItemList()) {
ItemCartIds.ItemCartId itemCartId = new ItemCartIds().new ItemCartId();
if (cartItemBean.getIsSelected()) {
itemCartId.setItemCartId(cartItemBean.getItemCartId());
idList.add(itemCartId);
}
}
itemCartIds.setItemCartIds(idList);
}
}
Gson gson = new Gson();
String idsStr = gson.toJson(itemCartIds);//需要进行替换itemCartIds,改为首字母大写,否则报错
// String idsStr = JSON.toJSONString(itemCartIds);//需要进行替换itemCartIds,改为首字母大写,否则报错
Debug.e(idsStr);
return ListUtils.isEmpty(itemCartIds.getItemCartIds()) ? "" : idsStr.contains("itemCartIds") ? idsStr.replace("itemCartIds", "ItemCartIds") : idsStr;
} else {
return "";
}
}
问题:升级到Android9 出现“Cleartext HTTP traffic to xxx not permitted”
针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接。解决方法有:
APP改用https请求
targetSdkVersion 降到27以下
最终暴力解决
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
network-security-config>
2. 在AndroidManifest.xml中
```xml
Caused by: android.view.InflateException: Binary XML file line #12: Binary XML file line #2: Error inflating class android.support.design.widget.CoordinatorLayout
Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class android.support.design.widget.CoordinatorLayout
Caused by: java.lang.reflect.InvocationTargetException
...
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
解决:
如果布局包含:
用以下内容代替:
如果布局包含:
用以下内容代替
如果布局包含:
用以下内容代替:
用以下内容代替:
read-only property 'outputFile'
问题:Gradle(3.3->4.4) Cannot set the value of read-only property ‘outputFile’ for ApkVariantOutputImpl_Decorated
保意项目:原来gradle3.3,build gradle 2.3.3
android{
...
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && "release" == variant.buildType.getName()) {
def fileName = "byguide_v${variant.mergedFlavor.versionName}_${getBuildTime("MMdd")}.apk"
output.outputFile = new File(output.outputFile.parent, fileName)
}
variant.mergedFlavor.versionName = variant.mergedFlavor.versionName + "." + getBuildTime("MMdd")
variant.mergedFlavor.versionCode = variant.mergedFlavor.versionCode * 10000 + getBuildTime("MMdd").toInteger()
}
}
}
def getBuildTime(String formatStr) {
new Date().format(formatStr)
}
升级后=》gradle4.4,build gradle 3.1.3
applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && "release" == variant.buildType.getName()) {
def fileName = "byguide_v${variant.mergedFlavor.versionName}_${getBuildTime("MMdd")}.apk"
outputFileName = fileName
}
output.versionNameOverride = variant.mergedFlavor.versionName + "." + getBuildTime("MMdd")
output.versionCodeOverride = variant.mergedFlavor.versionCode * 10000 + getBuildTime("MMdd").toInteger()
}
}
All flavors must now belong to a named flavor dimension
问题:Gradle(3.3->4.4)
All flavors must now belong to a named flavor dimension
defaultConfig {
//添加这一句
flavorDimensions "versionCode"
...
}
Could not resolve project :AliSDK.
Gradle(3.3->4.4)
AS3.1.3上面出现这个问题,换成AS3.6.2没有这个问题
unexpected element found in
问题:Gradle(3.3->4.4)
E:\...\debug\AndroidManifest.xml:107:9-109:62: AAPT: error: unexpected element
AliSDK
的AndroidManifest.xml
中
<manifest ...>
<activity android:name="com.alibaba.wxlib.util.RequestPermissionActivity"
tools:node="remove"/>
<application ...></application>
</manifest>
问题:Gradle(3.3->4.4) Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration. \- butterknife-7.0.1.jar...
各个module下的build.gradle中,都加上
android {
...
defaultConfig {
...
// 以上显示声明annotationProcess
javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } }
}
...
}
问题:Gradle(3.3->4.4) Unable to find method ‘org.gradle.api.tasks.compile.CompileOptions.setBootClasspath(Ljava/lang/String;)V’.
Unable to find method 'org.gradle.api.tasks.compile.CompileOptions.setBootClasspath(Ljava/lang/String;)V'.
Possible causes for this unexpected error include:
Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
Re-download dependencies and sync project (requires network)
The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
Stop Gradle build processes (requires restart)
Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.
In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.
出现这个问题是因为Gradle插件和Gradle版本不匹配的问题:
https://blog.csdn.net/shayubuhuifei/article/details/97775208
只需要修改Gradle对应的插件版本就好,gradle版本和插件版本对应表:
https://developer.android.google.cn/studio/releases/gradle-plugin.html#updating-plugin
toast报这个异常。解决:在主线程创建个Handler,toast写里面,需要吐司的地方去发送消息给这个handler
现象:view.setVisibility(View.INVISIBLE);
无效
原因一:对这个view设置了动画,且给此动画加了属性 anim.setFillAfter(true);
解决:
anim.setFillAfter(false);
view.setVisibility(View.INVISIBLE);
view.clearAnimation();
view.setVisibility(View.INVISIBLE);
view.postdelay延迟100毫秒
使用runOnUiThread的方式来实现
如果上述方案都不可行,检查Mainifest.xml,去除android:hardwareAccelerated="false"
对于其他原因,在setVisibility隐藏之后加个刷新。view.invalidate()或view.postinvalidate()。前面俩无效再试试自身requestLayout()或父容器的requestLayout()来强制页面刷新。
[android:android.content.res.Resources$NotFoundException: String resource ID #..](https://www.cnblogs.com/mybkn/archive/2012/07/09/2582958.html)
做Android应用开发的朋友有时候会遇到这样的Bug,,
android.content.res.Resources$NotFoundException: String resource ID #0x0 找不到资源文件ID #0x0
原因分析如下:
遇到这种情况,很有可能是把一个int型业务数据的 设置setText()或者类似的方法中, 这样Android系统就会主动去资源文件当中寻找, 但是它不是一个资源文件ID, 所以就会报出这个bug。 将int型业务数据,转换成String类型即可。
Android资源不是可绘制的(颜色或路径)
Resource is not a Drawable (color or path): TypedValue{t=0x2/d=0x7f040151 a=2}
android.view.LayoutInflater.createView(LayoutInflater.java:620)
异常分析:由于将图片资源拷贝到了drawable-land-xhdpi目录下,本来应该拷贝到drawable-xhdpi目录下
解决方法:
Caused by: org.gradle.api.internal.tasks.compile.CompilationFailedException: Compilation failed; see
删除build/intermediates 然后重新编译
当时遇到这个错误只知道是编译错误,不知道为什么,也定不了问题所在,网上说的一堆也试了,都没用
日志的错误说的也不清晰,有很多时候我都是Rebuild或清理工程就解决了,这次是因为集成极光分享,集成到一半又删了,没删干净,所以出现了这个问题,处理方法是把下图的文件夹删掉,重新编译,立马定位到代码块找不到极光的包,删除该代码就好了,因为上次集成极光编译是没问题的,删了极光后还有缓存,Android studio都没检测出来。
Manifest merger failed with multiple errors
可以看到是AndroidManifest出错
打开AndroidManifest,切换到Merged Manifest
,可以查看报错信息
The APK does not exist
问题:The APK file xxx.apk does not exist on disk. Error while Installing APK
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
// apk_渠道名-版本号-版本名称-编译时间.apk
def fileName = "xxx.apk"
tput.outputFile = new File(outputFile.parent, fileName)
}
}
给apk文件重命名时发生了问题, 如果除.apk之外的文件名中还包含. 的话, 可能会出现这个问题,
好吧 将重命名格式改的简单点, 问题就解决了
Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'. >
Unexpected scopes found in folder 'D:\twoMoveMent\app\build\intermediates\transforms\mergeJavaRes\debug'.
Required: PROJECT. Found: EXTERNAL_LIBRARIES, PROJECT, SUB_PROJECTS
解决方案:将bulid目录删掉 重新编译即可!!!!!少走弯路
Android stdio IDE环境下debug代码不显示变量值,add to watch无效
解决方案:
修改app.gradle 文件下的testCoverageEnabled为false
buildTypes {
debug {
minifyEnabled false
signingConfig signingConfigs.debug
testCoverageEnabled false
}
}
NormalDemocompile Classpath
问题Unable to resolve dependency for ':face@NormalDemo/compileClasspath': Could not resolve project :aliveDetect.
Open File
Show Details
Unable to resolve dependency for ':face@NormalDemoUnitTest/compileClasspath': Could not resolve project :aliveDetect.
Open File
Show Details
答案:
出现以上情况就是因为Could not resolve project :aliveDetect.
这个工程下的gradle
有问题,配置跟宿主工程有点不一样才会造成这样的
aliveDetect
的gradle
下面是这样的:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
app的gradle下面是这样的:
buildTypes {
debug({
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
})
demo({
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
})
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
注意到是因为app
的build.gradle
中多了一个demo
,,,,,,就是这个demo
引起的要么删除 要么就给我在aliveDetect
这个地方添加,这样就不会有错误了,也可以编译过去
不会造成 编译之后出现Try Again Open Messages View Show Log in Explorer.
transformClassesWithInstantRunForNormalDebug
问题java.lang.RuntimeException: com.android.build.api.transform.TransformException: java.lang.RuntimeException:Failed to find byte code for java/awt/RenderingHints$Key com.android.build.api.transform.TransformException: java.io.IOException: Failed to find byte code for java/awt/RenderingHints$Key
切记这个要一致:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
java.lang.OutOfMemoryError
问题:运行项目出现java.lang.OutOfMemoryError: GC overhead limit exceeded...
解决:在项目build.gradle中添加
android {
dexOptions {
javaMaxHeapSize "4g"
}
}
解决方案
该异常表示未能成功分配字节内存,通常是因为内存不足导致的内存溢出。
[解决方案]:OOM就是内存溢出,即Out of Memory。也就是说内存占有量超过了VM所分配的最大。怎么解决OOM,通常OOM都发生在需要用到大量内存的情况下(创建或解析Bitmap,分配特大的数组等),这里列举常见避免OOM的几个注意点:
1.适当调整图像大小。
2.采用合适的缓存策略。
3.采用低内存占用量的编码方式,比如Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省内存。
4.及时回收Bitmap。
5.不要在循环中创建过多的本地变量。
6.自定义对内存分配大小。
7.特殊情况可在mainfests的Application中增加 android:largeHeap="true"属性,比如临时创建多个小图片(地图marker)
Picasso导致的OutOfMemoryError 解决方案:
在application中添加android:largeHead="true"
<application
android:name=".MyApplication"
android:largeHeap="true"
android:icon="@mipmap/ic_launcher"
android:label="融商会"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjestPan">application>
unable to unzip
问题:Gradle build failed - unable to unzip
You have just to do in a Terminal (for have terminal : Select View > Tool Windows > Terminal) :
On Windows:
gradlew cleanBuildCache
On Mac or Linux:
./gradlew cleanBuildCache
And build Gradle
在app的build中
android {
...
defaultConfig {
...
//添加如下配置就OK了
javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } }
}
...
}
IllegalStateException: Can not perform this action after onSaveInstanceState:
onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存完状态后再给它添加Fragment就会报错。
解决:
把commit()
换成commitAllowingStateLoss()
其他延申
java.lang.IllegalStateException:Can't change tag of fragment d{e183845 #0 d{e183845}}: was d{e183845} now d{e183845 #0 d{e183845}}
java.lang.IllegalStateException:Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 37 path $.data
无法压缩回收位图
Can't compress a recycled bitmap
com.paidian.hwmc.utils.i.a(FileUtils.java:75)
如果位图已被回收,则希望抛出异常的方法将调用此值。知道了崩溃的具体位置,就该分析具体的原因呢!
public boolean compress(CompressFormat format, int quality, OutputStream stream) {
checkRecycled("Can't compress a recycled bitmap");
//省略代码
return result;
}
//如果位图已被回收,则希望抛出异常的方法将调用此值。
private void checkRecycled(String errorMessage) {
if (mRecycled) {
throw new IllegalStateException(errorMessage);
}
}
异常分析:
使用了已经被释放过内存的对象。对于Bitmap
:Bitmap bitmap=一个bitmap对象
。使用过程中调用bitmap.recycle()
,之后再使用bitmap就会报错。
bitmap.recycle()
解释:释放与此位图关联的本机对象,并清除对象数据的引用。这将不会同步释放对象数据。它只允许在没有其他引用的情况下对其进行垃圾手机。位图被标记为“死”,这意味着如果调用getPixels()
或setPixels()
它将抛出异常,而不会绘制任何内容。此操作不能反转,因此只有在确定没有进一步使用位图的情况下才应该调用该操作。这个一个高级调用,通常不需要调用,因为当没有对此位图的引用时,普通GC进程将释放此内存。
Free the native object associated with this bitmap, and clear the reference to the pixel data
解决方法:
if(mBitmap.isRecycled()) return null;
参数不匹配异常,通常由于传递了不正确的参数导致
常见的出现场景
解决方法:(采取不信任原则)
android.view.WindowManager$BadTokenException
Unable to add window -- token android.os.BinderProxy@7f652b2 is not valid; is your activity running?
异常分析:
Toast.makeText(this,"潇湘剑雨-yc",Toast.LENGTH_SHORT).show();
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
解决方法:
哪些情况会发生该问题?