记录一些项目中碰到的小问题,小知识
1. jar 包与 aar 包
1.1 Android Studio 导出 jar 包
(1)在一个 Project 中加入 Module,即项目中新建 Module:
File → new module → Android Library(这里我命名为 mylibrary);
(2)在新建的 library 中新建要用的 java 类;
(3)在 app 中引入此 module,即在 app 的build.gradle 中加入此 module 的 dependency,如下:
dependencies{
compile 'com.android.support.appcompat-v7:21.0.3'
compile project (':mylibrary')
}
(4)项目编译之后 jar 包就生成了,可在下面的两个目录中找到:
- ./mylibrary/build/intermediates/bundles/debug/class.jar
- ./mylibrary/build/intermediates/bundles/releases/class.jar
1.2 Android Studio 导入 jar 包
复制 jar 包到 app 的 libs 目录下,接着右键 → Add as Library 即可。
1.3 Android Studio 添加 aar 包引用
(1)复制 aar 包到 app 的 libs 目录下;
(2)配置 build.gradle 文件:
a. 添加:
respositories{
flatDir{
dirs 'Libs'
}
}
b. 修改 dependencies,添加一行:
compile(name:'aar文件名称',ext:'aar')
(3)重新编译项目,编译完后在 app/build/intermediates/exploded-aar/ 可看到引用 aar 包的内容。
2. 其他杂项
2.1 在 activity 中获取另一个 xml 布局中的控件:
LayoutInflater layout = this.getLayoutInflater();
View view = layout.inflate(R.layout.布局名, null);
Button b = (Button)view.findViewById(R.id.b);
2.2 尽量减少对变量的重复计算,如:
for(int i = 0; i < list.size(); i++){ ... }
可替换为
for(int i = 0, length = list.size(); i < length; i++){ ... }
2.3 在多个 fragment 中,一些 fragment 特殊需求只支持竖屏,则可以:
在横竖屏都可用的 fragment 中的 onCreateView 中添加:
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
在只支持竖屏的 fragment 中的 onCreateView 中添加:
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PROTRAIT);
Acivity 的一些屏幕属性:
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE // 指定横屏
ActivityInfo.SCREEN_ORIENTATION_PROTRAIT // 竖屏
ActivityInfo.SCREEN_ORIENTATION_USER // 用户朝向
ActivityInfo.SCREEN_ORIENTATION_NOSENSOR // 不受重力影响
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE // 横屏动态切换
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PROTRAIT // 竖屏动态切换
...
2.4 网页界面 WebView 中可返回,则可以:
// 设置返回键监听
myWebView.setOnKeyListener(backListener);
. . .
private View.OnKeyListener backListener = new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
if (i == KeyEvent.KEYCODE_BACK) {
if(myWebView.canGoBack()) {
myWebView.goBack();//返回上一页面
return true;
} else {
. . .
}
}
}
return false;
}
};
2.5 命令行进入线上keystore的文件所在目录,然后输入如下命令,即可查看签名:
keytool -list -v -keystore app-release.jks
其中 app-release.jks 是指你要查看签名的 keystore 文件。
3 项目中碰到的一些bug
3.1 app 安装失败
报上图中的错误是因为可能有以下几个原因:
如图中所说手机上有其他版本app
解决方法是直接点击 OK,卸载其他版本的 app用真机测试时,手机设置了禁止 USB 安装app
解决方法是手机设置允许 USB 安装appAndroidManifest 编写出错(很常见)
解决方法是检查AndroidManifest 文件,看看是不是多写或少写一些东西,比如少了诸如 “.”、“:” 等这类标点符号,或者多了其他不必要的东西其他原因(手动滑稽)
3.2 java.lang.RuntimeException: Parcel: unable to marshal value
使用 Parcel 序列化在两个 Activity 或 Fragment 中进行数据传送,Parcel 需要实现 Parcelable 接口。而如果在 Parcel 类中,若需要读或者写其他的 bean 数据的话,这些 bean 需要实现 Serializable 或 Parcelable 序列化接口。否则会出现如标题所示错误。
3.3 android studio 在电脑蓝屏后或意外重启后 报错的解决方法
问题描述:在用studio开发项目的时候电脑突然蓝屏了,重启电脑之后打开项目各种红线,原本的import全部报错。
解决方法:File -> Invalidate Cashes / Restart
参考:
在电脑蓝屏后 报错的解决方法
android studio意外重启后 原本的import全部报错
3.4 Glide 加载图片底色变绿
Glide 使用 bitmap 的编码为 RGB565,所以有时由于过度压缩导致图片变绿,因此要改变一下 Glide 的 bitmap 编码:
public class GlideConfiguration implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
@Override
public void registerComponents(Context context, Glide glide) {
}
}
接着在 AndroidManifest 中添加:
<!-- 防止 Glide 加载图片底色变绿 -->
<meta-data
android:name="com.xxx.xxx.GlideConfiguration"
android:value="GlideModule"/>
参考: Android Glide 图片加载框架图片变色变绿解决方法
3.5 ImageView 设置了 scaleType="centerCrop"
Glide 加载圆角图片无效
public class GlideRoundedCornersTransform extends CenterCrop {
private float mRadius;
private CornerType mCornerType;
private static final int VERSION = 1;
private static final String ID = BuildConfig.APPLICATION_ID + "GlideRoundedCornersTransform." + VERSION;
private static final byte[] ID_BYTES = ID.getBytes(CHARSET);
/**
* 待处理的圆角枚举
*/
public enum CornerType {
ALL,
TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT,
TOP, BOTTOM, LEFT, RIGHT,
TOP_LEFT_BOTTOM_RIGHT,
TOP_RIGHT_BOTTOM_LEFT,
TOP_LEFT_TOP_RIGHT_BOTTOM_RIGHT,
TOP_RIGHT_BOTTOM_RIGHT_BOTTOM_LEFT,
TOP_LEFT_TOP_RIGHT
}
public GlideRoundedCornersTransform(float radius, CornerType cornerType) {
super();
mRadius = radius;
mCornerType = cornerType;
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
Bitmap transform = super.transform(pool, toTransform, outWidth, outHeight);
return roundCrop(pool, transform);
}
private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
if (source == null) {
return null;
}
int width = source.getWidth();
int height = source.getHeight();
Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config
.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader
.TileMode.CLAMP));
paint.setAntiAlias(true);
Path path = new Path();
drawRoundRect(canvas, paint, path, width, height);
return result;
}
private void drawRoundRect(Canvas canvas, Paint paint, Path path, int width, int height) {
float[] rids;
switch (mCornerType) {
case ALL:
rids = new float[]{mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_LEFT:
rids = new float[]{mRadius, mRadius, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_RIGHT:
rids = new float[]{0.0f, 0.0f, mRadius, mRadius, 0.0f, 0.0f, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case BOTTOM_RIGHT:
rids = new float[]{0.0f, 0.0f, 0.0f, 0.0f, mRadius, mRadius, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case BOTTOM_LEFT:
rids = new float[]{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, mRadius, mRadius};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP:
rids = new float[]{mRadius, mRadius, mRadius, mRadius, 0.0f, 0.0f, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case BOTTOM:
rids = new float[]{0.0f, 0.0f, 0.0f, 0.0f, mRadius, mRadius, mRadius, mRadius};
drawPath(rids, canvas, paint, path, width, height);
break;
case LEFT:
rids = new float[]{mRadius, mRadius, 0.0f, 0.0f, 0.0f, 0.0f, mRadius, mRadius};
drawPath(rids, canvas, paint, path, width, height);
break;
case RIGHT:
rids = new float[]{0.0f, 0.0f, mRadius, mRadius, mRadius, mRadius, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_LEFT_BOTTOM_RIGHT:
rids = new float[]{mRadius, mRadius, 0.0f, 0.0f, mRadius, mRadius, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_RIGHT_BOTTOM_LEFT:
rids = new float[]{0.0f, 0.0f, mRadius, mRadius, 0.0f, 0.0f, mRadius, mRadius};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_LEFT_TOP_RIGHT_BOTTOM_RIGHT:
rids = new float[]{mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_RIGHT_BOTTOM_RIGHT_BOTTOM_LEFT:
rids = new float[]{0.0f, 0.0f, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius};
drawPath(rids, canvas, paint, path, width, height);
break;
case TOP_LEFT_TOP_RIGHT:
rids = new float[]{mRadius, mRadius, mRadius, mRadius, 0.0f, 0.0f, 0.0f, 0.0f};
drawPath(rids, canvas, paint, path, width, height);
break;
default:
throw new RuntimeException("RoundedCorners type not belong to CornerType");
}
}
/**
* @param rids 圆角的半径,依次为左上角xy半径,右上角,右下角,左下角
*/
private void drawPath(float[] rids, Canvas canvas, Paint paint, Path path, int width, int height) {
path.addRoundRect(new RectF(0, 0, width, height), rids, Path.Direction.CW);
canvas.drawPath(path, paint);
}
@Override
public boolean equals(Object o) {
return o instanceof GlideRoundedCornersTransform;
}
@Override
public int hashCode() {
return ID.hashCode();
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
messageDigest.update(ID_BYTES);
}
}
使用:
RequestOptions mOptions = new RequestOptions().optionalTransform(new
GlideRoundedCornersTransform(10, GlideRoundedCornersTransform.CornerType.ALL));
Glide.with(this).load(imgUrl).apply(mOptions).into(imageView);
参考: Android Glide4.7.1下的圆角处理与高斯模糊
3.6 报错:BroadcastReceiver components are not allowed to register to receive intents
原因:context.registerReceiver()
不能在 BroadcastReceiver 的 onReceive()
里面调用。
解决:提高context
的级别,使用context.getApplicationContext().registerReceiver()
即可。
3.7 volatile 关键字的作用(针对多线程情况下)
- CPU高速缓存和可见性问题
- 禁止指令重排
使用方法:
Java:变量的前面加上 volatile
关键字即可
Kotlin:变量的前面加上 @Volatile
注解即可
3.8 AndroidStudio更新4.1无法启动问题解决方法
问题:最近AndroidStudio4.1正式版本发布,点了更新提示先更新插件,下载完后重启AndroidStudio,结果无法启动了,报如下错误:
java.lang.NoSuchMethodError: com.intellij.ide.plugins.PluginManagerCore.getEnabledPluginRawList()Ljava/util/List;
解决:
windows:删除 ...\.AndroidStudio4.0\config\plugins
下面的 marketplace
文件夹,可以启动但没有更新到4.1成功。
mac电脑可参考:https://blog.csdn.net/bingjianIT/article/details/109142316
3.9 AndroidStudio 启动模拟器问题
3.9.1 Emulator: glTexImage2D: got err 类错误的解决方法
打开模拟器 Settings ,选择 Advanced:
把OpenGL ES Renderer
改为SwiftShader
把OpenGL ES API level
改为Renderer maximum
持续更新中...