Android 开发问题
Posted 元气小嘉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 开发问题相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
android开发问题
提示:以下是本篇文章正文内容,下面案例可供参考
1.Fragment 内findViewByid空指针问题
Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
解决方法:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
// Inflate the layout for this fragment
View v=inflater.inflate(R.layout.fragment_main, container, false);
smartRefreshLayout= v.findViewById(R.id.smart_refreshLayout);
grid_div=v.findViewById(R.id.grid_divs);
tv_add_dev =v.findViewById(R.id.tv_add_dev);
layout_2_set_location =v.findViewById(R.id.layout_2_set_location);
return v;
2.getApplication 空指针问题
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ‘android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()’ on a null object reference
解决办法:定义可以在OnCreat外,但FindViewByid要在Oncreat内。
3.NullPointerException异常:
FragmentManager.beginTransaction()
Fragment fragment =this.getsupportFragmentManager();
4.Can’t toast on a thread that has not called Looper.prepare()问题
问题描述:
java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()
如果在一个线程中没有调用Looper.prepare(),就不能在该线程中创建Toast。这个问题是因为在子线程中弹出Toast导致的。
解决办法:先调用Looper.prepare();再调用Toast.makeText().show();最后再调用Looper.loop();
Looper.prepare();
Toast.makeText(Modify_pho_or_passActivity.this,"修改成功!",Toast.LENGTH_LONG).show();
Looper.loop();
5.okhttp3 response内的数据无法在外部使用
问题描述:在okhttp中我们成功的访问后台,然后从onResponse中获得了返回的json数据),这个返回的数据只能在onResponse方法内调用,放到方法外这个数据就无法使用,追根揭底就是okhttp是异步请求,你没办法将异步请求的结果放到主线程中使用。
自己使用的RecycleView,在onResponse外使用,无数据进adapter;在onResponse内使用,提示
Only the original thread that created a view hierarchy can touch its views.
异常的意思是说只有创建这个view的线程才能操作这个 view,普通会认为是将view创建在非UI线程中才会出现这个错误。
–
解决办法:在onResponse内创建了runOnUiThread,写入recycleView的配置,将其在主线程中操作。
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException
final String responseData = response.body().string();
//解析json
devices = JsonManager.parseJsonArray(responseData, DeviceEntity.class);
// Log.e("devices",devices.get(0).getDevicename());
runOnUiThread(new Runnable()
@Override
public void run()
if(devices!=null)
rv_devices_list.setLayoutManager(new LinearLayoutManager(DeviceManagerActivity.this));
devListAdapter =new DevListAdapter(devices);
rv_devices_list.setAdapter(devListAdapter);
// rv_devices_list.setVisibility(View.VISIBLE);
);
);
6.TabLayout 加载适配器后TabItem不显示问题
问题描述:
在XMl文件中静态加载TabItem,tabLayout.setupWithViewPager(viewPager)之前可以显示,之后就不能显示。
原因及解决办法:
https://blog.csdn.net/sundy_tu/article/details/52682246
最好从PageAdapter内动态添加TabItem。
@Nullable
@Override
public CharSequence getPageTitle(int position)
title.clear();
title.add("查询数据");
title.add("统计数据");
return title.get(position);
7.Adapter内设置字体颜色无效
参考链接
有效:
holder.tv_1.setTextColor(Color.parseColor(“#FF0000”));
无效:
holder.tv_1.setTextColor(R.color.red);
Android 开发问题总结 四
Android 开发问题总结 四
- 1、Android 悬挂式通知栏的实现
- 2、Android 8.0以上使用手机相册、相机以后图片保存、裁剪是会出现android.support.v4.content.FileProvider的使用权限问题
- 3、Litpal 2.0数据库使用过程中id主键自动从 0开始。但是其他sqlite 数据库默认从1 开始。
- 4、关于TextView 支持html标签的问题
- 5、Glide 图片加载库在使用asBitmap 的时候。偶现同一个ImageView会显示其他页面加载的bitmap图片。
- 6、合并不同仓库的代码。并同步提交:
- 7、Android SDK版本名和API level对照表
- 8、Glide接入后出现 ERROR: Failed to resolve: disklrucache。
- 9、恢复删除分支提交的commit
- 10、通过Drawable来改变对应控件或者布局文件中的颜色:
- 11、Build was configured to prefer settings repositories over project repositories but repository 'BintrayJCenter' was added by build file 'build.gradle'
- 12、FTS全文搜索功能搜索速度慢的问题
- 13、Android部分手机长时间后台或者频繁连接网络的情况,系统有特殊场景会把应用添加到限制联网的状态,需要手动在设置或者应用设置里边进行开启
- 14、 通过hook IActivityManager 来捕获reportSizeConfigurations 异常带来的崩溃
- 15、unsupported class file major version 62 gradle
- 16、可能导致TransactionTooLargeException crash的几种情况
- 17、项目升级Android12 (31)以后,编译release版本报错"-keepclassmembers class * *** @(android.view.View); "
- 18、Android 暗黑模式适配中,出现了暗黑模式跟亮色同时存在的情况,导致页面显示异常
- 19、Android源码网址
- 20、Java中使用HttpsURLConnection时需要特别注意的点
1、Android 悬挂式通知栏的实现
Android 悬挂式通知是Android 在5.0以后才有的。在5.0以前通过设置setTicker 来实现
。在5.0 以上、8.0以上通过设置setFullScreenIntent。在8.0以上需要设置
NotificationChannel 的优先级为NotificationManager.IMPORTANCE_HIGH
即可。但是在使用过程中可能会出现很多特殊情况。
比如:悬挂通知栏无法弹窗、会直接进入目标Activity、或者其他情况。
下边是适配过的悬挂式通知栏实例代码:
//获取PendingIntent
android.app.NotificationManager notificationManager = (android.app.NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent();
PendingIntent mainPendingIntent = PendingIntent.getBroadcast(context, Integer.valueOf(alramId), intent, FLAG_UPDATE_CURRENT);
RemoteViews views = new RemoteViews(Application.getInstance().getPackageName(),R.layout.notify_drop);
NotificationCompat.Builder builder = new NotificationCompat.Builder(TimeApplication.getInstance());
builder.setLargeIcon(BitmapFactory.decodeResource(TimeApplication.getInstance().getResources(),R.mipmap.ic_launcher))
.setSmallIcon(R.mipmap.ic_launcher)//不能缺少的一个属性
.setContentIntent(mainPendingIntent)
.setCustomContentView(views)
.setAutoCancel(true)
.setLights(0, 0, 0)
.setWhen(System.currentTimeMillis());//设置通知时间
builder.setDefaults(Notification.DEFAULT_ALL);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
NotificationChannel channel;
if(eventDataEntity.soundposition == 0)
channel = new NotificationChannel(String.valueOf(CHANNEL_ID), "提醒通知", NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
channel.getAudioAttributes();
notificationManager.createNotificationChannel(channel);
builder.setChannelId(String.valueOf(CHANNEL_ID));
builder.setCustomContentView(views);
else
channel = new NotificationChannel(String.valueOf(CHANNEL_CUSTOM_ID), "自定义铃声提醒通知", NotificationManager.IMPORTANCE_HIGH );
channel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
channel.getAudioAttributes();
channel.setSound(null,null);
notificationManager.createNotificationChannel(channel);
builder.setChannelId(String.valueOf(CHANNEL_CUSTOM_ID));
builder.setCustomContentView(views);
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
if(isNeedSetFullScreen())
CustomLog.e("提醒事件 === 2");
builder.setFullScreenIntent(mainPendingIntent,true);
// builder.setVisibility(Notification.VISIBILITY_PUBLIC);
// builder.setTicker("悬浮通知");
// builder.setDefaults(Notification.DEFAULT_ALL);
// builder.setPriority(Notification.PRIORITY_MAX);
notificationManager.notify(Integer.parseInt(alramId), builder.build());
/**
* 是否需要设置setFullScreenIntent
* @return
*/
public static boolean isNeedSetFullScreen()
CustomLog.e("当前手机品牌 =" + Build.MANUFACTURER);
boolean isNeed;
switch (Build.MANUFACTURER)
case MANUFACTURER_HUAWEI://华为
case MANUFACTURER_Huawei:
isNeed = false;
break;
case MANUFACTURER_MEIZU://魅族
isNeed = false;
break;
case MANUFACTURER_XIAOMI://小米
isNeed = false;
break;
case MANUFACTURER_SONY://索尼
isNeed = false;
break;
case MANUFACTURER_OPPO://oppo
isNeed = false;
break;
case MANUFACTURER_LG://lg
isNeed = false;
break;
case MANUFACTURER_LETV://乐视
isNeed = false;
break;
case MANUFACTURER_VIVO:
isNeed = true;
break;
case MANUFACTURER_SAMSUNG:
isNeed = false;
break;
case MANUFACTURER_ZTE:
isNeed = false;
break;
case MANUFACTURER_YULONG:
isNeed = false;
break;
case MANUFACTURER_LENOVO:
isNeed = false;
break;
default:
isNeed =true;
break;
return isNeed;
2、Android 8.0以上使用手机相册、相机以后图片保存、裁剪是会出现android.support.v4.content.FileProvider的使用权限问题
在使用裁剪的时候必须添加以下代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//通过FileProvider创建一个content类型的Uri
// uri = FileProvider.getUriForFile(this, "包名.fileProvider", file);
3、Litpal 2.0数据库使用过程中id主键自动从 0开始。但是其他sqlite 数据库默认从1 开始。
修改litpal默认主键id 的初始化值,需要覆写
@Override
public void assignBaseObjId(int baseObjId)
//修改初始值为 1 ,修改时一定要注意这样使用会不会对你现有的逻辑发生影响。
super.assignBaseObjId(1);
4、关于TextView 支持html标签的问题
目前支持的html标签很基础,p 、h 、font 等等。
span标签在6.0以上的手机系统已经开始支持,6.0以下不起作用。如果是字体颜色等的调整可以使用font。
5、Glide 图片加载库在使用asBitmap 的时候。偶现同一个ImageView会显示其他页面加载的bitmap图片。
原因:因为Glide 库底层对bitmap 有复用的处理。而且是指向同一块内存地址。所有在加载其他bimap图片的时候。只是改变了内容,地址没有变化。这个时候其他ImageView或者控件在使用的时候,就会变成该地址所对应的最新的bitmap 图片。
修改:
使用时只要重新创建Bitmap 对象。而不是直接使用Glide 返回的bitmap。
6、合并不同仓库的代码。并同步提交:
git init
git remote add trans_old https://××××××××××.git (旧的git仓库代码地址)
git remote add trans_new https://×××××××××.git (新的git仓库代码地址)
git fetch trans_old
git fetch trans_new
git checkout -b trans_new/branchName
git merge trans_old/branchName
git push trans_new trans_new/branchName
7、Android SDK版本名和API level对照表
SDK版本名 | API Level |
---|---|
Android 9.0 (Pie) | 28 |
Android 8.1 (Oreo) | 27 |
Android 8.0 (Oreo) | 26 |
Android 7.1.1 (Nougat) | 25 |
Android 7.0 (Nougat) | 24 |
Android 6.0 (Marshmallow) | 23 |
Android 5.1 (Lollipop) | 22 |
Android 5.0 (Lollipop) | 21 |
Android 4.4W (KitKat Wear) | 20 |
Android 4.4 (KitKat) | 19 |
Android 4.3 (Jelly Bean) | 18 |
Android 4.2 (Jelly Bean) | 17 |
Android 4.1 (Jelly Bean) | 16 |
Android 4.0.3 (IceCreamSandwich) | 15 |
Android 4.0 (IceCreamSandwich) | 14 |
Android 3.2 (Honeycomb) | 13 |
Android 3.1 (Honeycomb) | 12 |
Android 3.0 (Honeycomb) | 11 |
Android 2.3.3 (Gingerbread) | 10 |
Android 2.3 (Gingerbread) | 9 |
Android 2.2 (Froyo) | 8 |
Android 2.1 (Eclair) | 7 |
Android 2.0.1 (Eclair) | 6 |
Android 2.0 (Eclair) | 5 |
Android 1.6 (Dout) | 4 |
Android 1.5 (Cupcake) | 3 |
Android 1.1 (Base) | 2 |
Android 1.0 (Base) | 1 |
8、Glide接入后出现 ERROR: Failed to resolve: disklrucache。
解决版本,修改build.gradle文件。
替换为
buildscript
repositories
jcenter
url 'https://jcenter.bintray.com/'
maven
url 'https://maven.google.com'
// url 'http://maven.aliyun.com/nexus/content/repositories/releases/' //阿里云仓库地址
// maven
// url 'http://maven.aliyun.com/nexus/content/repositories/releases/' //阿里云仓库地址
//
// maven
// url 'http://maven.aliyun.com/nexus/content/repositories/releases/' //阿里云仓库地址
//
google()
maven
url "http://10.241.11.54:18080/nexus/repository/maven-open-releases/"
maven
url "http://10.241.11.54:18080/nexus/repository/maven-open-snapshots/"
dependencies
classpath 'com.android.tools.build:gradle:3.5.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
allprojects
repositories
flatDir
dirs 'libs'
maven
url 'https://maven.google.com'
// url 'http://maven.aliyun.com/nexus/content/repositories/releases/' //阿里云仓库地址
//
maven
url 'https://maven.google.com'
// url 'http://maven.aliyun.com/nexus/content/repositories/releases/' //阿里云仓库地址
jcenter
url 'https://jcenter.bintray.com/'
maven url 'http://developer.huawei.com/repo/'
maven url 'https://jitpack.io'
google()
maven
url "http://10.241.11.54:18080/nexus/repository/maven-open-releases/"
maven
url "http://10.241.11.54:18080/nexus/repository/maven-open-snapshots/"
task clean(type: Delete)
delete rootProject.buildDir
9、恢复删除分支提交的commit
- git log -g 查找提交的commit,并记录commit_id
- git branch “branch” commit_id
- 切换到“branch”分支,检查文件是否存在,即可。
10、通过Drawable来改变对应控件或者布局文件中的颜色:
例如需要 动态改变xml文件中的loading 效果的颜色。
实现方式有很多种,以下只是其中一种实现方式:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/icon_reader_progress_loading"
android:fromDegrees="0.0"
android:pivotX="50.0%"
android:pivotY="50.0%"
android:interpolator="@android:anim/anticipate_interpolator"
android:duration="500"
android:toDegrees="360.0" />
在ProgressBar中使用该xml文件,可以实现loading 加载动效。
<ProgressBar
android:id="@+id/web_reader_progressBar_loading"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateDuration="1500"
android:indeterminateDrawable="@drawable/web_progress_drawable_circle_wite" />
因为使用的是图片,而且图片是在xml文件中,那么通过正常方式是无法动态来改变loading的颜色。
但是通过Drawable 确可以实现,Drawable 是Android 中的一个类。
以下是改变颜色的方法:
Drawable drawable = mProgressLoading.getIndeterminateDrawable();
String color = “#333333”;
int color_loading = Color.parseColor(color);
drawable.setColorFilter(color_loading, PorterDuff.Mode.SRC_ATOP);
11、Build was configured to prefer settings repositories over project repositories but repository ‘BintrayJCenter’ was added by build file ‘build.gradle’
Gradle 版本升级到7.0以上以后,需要去项目seeting.gradle 文件中进行设置,build.gradle设置不生效了
12、FTS全文搜索功能搜索速度慢的问题
Fts是用来做在大数据量的时候提供搜索效率、时间的一种实现,目前Android支持FTS3\\4\\5 三种版本。fts搜索是基于索引文本分词来进行查询的,但是如果索引的文本特别复杂,数据长度过大,特殊符号特别多,那么需要注意了,因为特殊符号是FTS中进行分词的分割符,这个会导致分词量增多,搜索时间指数级上涨。所有创建fts索引需要注意数据的复杂程度。(建议4000字符以下,超过的建议以文本方式使用)。
13、Android部分手机长时间后台或者频繁连接网络的情况,系统有特殊场景会把应用添加到限制联网的状态,需要手动在设置或者应用设置里边进行开启
如果使用过程中出现应用网络异常的情况,但是其他应用可以正常使用,那么就需要排查以下几点
- 是否添加了网络访问权限
- 是否是使用http,而且清单文件中没有设置允许明文传输,需要在清单文件进行设置
- 需要检测是否是服务端ip、域名不可用
- 需要检查是否应用被系统限制了联网(可用去联网控制进行查看)
- 可用通过检测手机所有网卡的联网状态(可用通过代码实现)
- 可用批量通过测试服务器端所有端口进行测试连通性
14、 通过hook IActivityManager 来捕获reportSizeConfigurations 异常带来的崩溃
public class HookIActivityManager
public static final String TAG = "HookActivityManager";
public static HookIActivityManager hookIActivityManager = new HookIActivityManager();
private void HookIActivityManager()
public static HookIActivityManager getInstance()
return hookIActivityManager;
protected void init()
try
Field am = ActivityManager.class.getDeclaredField("IActivityManagerSingleton");
am.setAccessible(true);
Object iActivityManagerSingleton = am.get(null);
Class singletonCls = iActivityManagerSingleton.getClass().getSuperclass();
Field instance = singletonCls.getDeclaredField("mInstance");
instance.setAccessible(true);
Object iActivityManager = instance.get(iActivityManagerSingleton);
Class iActivityManagerCls = Class.forName("android.app.IActivityManager");
Class[] classes = iActivityManagerCls;
Object iActivityManageProxy = Proxy.newProxyInstance(
iActivityManagerCls.getClassLoader(),
classes,
new IActivityManagerProxy(iActivityManager));
instance.set(iActivityManagerSingleton, iActivityManageProxy);
catch (Exception e)
Log.d("HookActivityManager", "" + e);
private class IActivityManagerProxy implements InvocationHandler
private Object iActivityManager;
public IActivityManagerProxy(Object iActivityManager)
this.iActivityManager = iActivityManager;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
if ("reportSizeConfigurations".equals(method.getName()))
try
Log.w(TAG, "reportSizeConfigurations invoke execute ");
return method.invoke(iActivityManager, args);
catch (Exception e)
Log.w(TAG, "reportSizeConfigurations exception: " + e.getMessage());
return method.invoke(iActivityManager, args);
15、unsupported class file major version 62 gradle
该问题是由于Gradle 与java版本不一致,导致Gradle编译失败,可以调整java版本或者调整gradle版本。
16、可能导致TransactionTooLargeException crash的几种情况
虽然可以看出是binder中传递了过大的数据,但是要定位具体是哪里传递了过大的数据并没有那么容易;
以下为可能出现的几种情况:
- 1、activity或者fragment跳转时,传递的bundle携带了过大的数据,比如传递了bitmap或者size很大的ArrayList;可以使用toolargetool查看。
- 2、Activity.onSaveInstanceState()保存了过大的数据
- 3、FragmentStatePagerAdapter的saveState保存了过多的历史Fragment实例的状态数据,重写saveState
17、项目升级Android12 (31)以后,编译release版本报错"-keepclassmembers class * *** @(android.view.View); "
问题原因:
开启了混淆
项目中布局文件使用了android:onClick=“click 方法”
如果没有混淆需求可以直接关闭混淆;
否则需要删除所有布局文件中的onClick写法。
18、Android 暗黑模式适配中,出现了暗黑模式跟亮色同时存在的情况,导致页面显示异常
问题原因:
AppCompatDelegate.setDefaultNightMode(int mode)
该方法设置以后,如果应用或者系统中存在横竖屏切换的应用,那么横竖屏切换以后会导致该方法设置的状态不生效。从而出现错乱,需要在切到主页或者某些统一的位置进行重新设置。
19、Android源码网址
包含android源码下载、build、在线源码查找等.
20、Java中使用HttpsURLConnection时需要特别注意的点
HttpsURLConnection提供了一个静态方法setDefaultSSLSockeFactory()。 可以提供一个自定义javax.net.ssl.TrustManager,用来做CA证书握手和验证等。但是,这将覆盖JVM中所有“ https” URL的默认值!
目前因该设置导致的问题:
1、FireBase crash 数据统计上报调用以后,在Firebase后台无法看到。
是因为代码中调用setDefaultSSLSocketFactory方法导致FireBase数据上报使用了错误的sslSocketFactory对象,导致验证没有通过。
可以使用单独对某个对象设置setSSLSocketFactory。
以上是关于Android 开发问题的主要内容,如果未能解决你的问题,请参考以下文章
Android 11 (API 30) ContentProvider开发及碰到的问题 (Unknown URL content)