写这篇文章主要是为了方便查看在开发中出现的一些问题和解决方法,因为目前平时开发中出现的错误都是记录在笔记本上,一个是不易于保存,而是不易于查看,所以就有了写到这里的想法,这样随时随地都能看到;这篇文章将会不定期更新
Installation did not succeed.
The application could not be installed.
Installation failed due to: 'pm install-create -r -t -S 24942568' returns error 'UNSUPPORTED'
Retry
我这个是刚更新到as3.5,测试手机是红米,解决方式是在开发者选项界面,拉到最底下,把MIUI优化选项给关闭了,再运行就正常了
这个问题我感觉大家应该都会碰到:
当应用安装完成,通常会有一个完成提示界面,下方有两个按钮:完成、打开,如图
实际测试过程中发现现在很多高版本手机在应用市场下载应用安装后不会弹出安装界面,有点类似于静默安装的效果;但是很多6.0及以下的手机会出现安装界面及完成界面
重点是这里有两个按钮,如果你点击完成,手机会退出到桌面,这种情况下一切正常;但是你如果点击打开按钮,就会进入应用界面;比方说进入第一个ActivityA,然后打开第二ActivityB,你以为还是一切正常,但是当你按home键回到桌面,再点击图标进入应用,你以为看到的是ActivityB,但实际上居然是ActivityA;重复这一步骤,你会发现打开的永远是ActivityA;同时当你按返回键,会发现返回到ActivityB,再返回就到了ActivityA,感觉是系统重复的实例化ActivityA
下载了应用市场的一些应用也发现了这种现象,我觉得这是Android系统的一个bug,既然你提供了这两个按钮,那不应该出现这种情况;主要原因是从安装界面打开App和从桌面打开App的任务栈不一样,大家可以打印Intent信息看看,解决办法如下:
在应用第一个Activity的onCreate方法添加如下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!this.isTaskRoot()) {
Intent intent = getIntent();
if(intent !=null) {
String action = intent.getAction();
if(intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
finish();
return;
}
}
}
setContentView(R.layout.activity_main);
}
isTaskRoot 是系统api,作用是判断Activity是不是任务栈的源Activity(上面也说了,home键退出重新进入,又打开了第一个ActivityA,显然不是源Activity,它处在另一个任务栈;如果从正常启动,它就是源Activity),不是就是说被系统重新实例化出来了,此时再判断是否是主界面,如果是主界面就销毁当前的任务栈,让系统调出已经存在的任务栈,即你按home键退出时的界面所在 的任务栈
有些情况下WebView中加载一些资源会失败,其中一个原因就是在Android 5.0开始WebView默认不允许加载http与https混合页面,即不支持同时加载Https和Http请求,比如https页面加载http图片或者http页面加载https图片,那图片就显示不出来;这时可以通过如下方法进行设置
//https与http混合资源加载
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
该方法设置WebView的加载模式,参数有三种选择:
描述: 当PhotoView 和 ViewPager 组合时 ,用双指进行放大时 是没有问题的,但是用双指进行缩小的时候,程序就会崩掉
原因: 多次触发触摸屏事件,导致对同一个事件处理的消息过多,当第一个消息已处理完事件并销毁事件时,
由于该事件已销毁但还没来得及通知销毁第二个同样的消息,当主线程执行第二个消息时,由于获取不了该事件,
所以抛出异常。简单理解就是2个控件对同一个MotionEvent出现了冲突.
解决: 自定义一个类去继承ViewPager ,然后重写Viewpager的 onInterceptTouchEvent()的方法,捕捉该异常。
/**
* Created by cxy
* on 2017/7/5.
* 解决 photoview 与viewpager 组合时 图片缩放的错误 ;
* 异常:.IllegalArgumentException: pointerIndex out of range
*/
public class PhotoViewPager extends ViewPager{
public PhotoViewPager(Context context) {
super(context);
}
public PhotoViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
return false;
}
}
原因: 在getItemPosition()方法的源码中如果item的位置如果没有发生变化,则返回POSITION_UNCHANGED。
如果返回了POSITION_NONE,表示该位置的item已经不存在了。默认的实现是假设item的位置永远不会发生变化,
而返回POSITION_UNCHANGED。
解决: 修改适配器的写法,覆盖getItemPosition()方法,当调用notifyDataSetChanged时,
让getItemPosition方法人为的返回POSITION_NONE,从而达到强迫viewpager重绘所有item的目的。
当使用Fragment去嵌套另外一些子Fragment的时候,我们需要去管理子Fragment,这时候需要调用ChildFragmentManager去管理这些子Fragment,由此可能产生的Exception主要是: Java.lang.IllegalStateException: No activity
描述:当第一次从一个Activity启动Fragment,然后再去启动子Fragment的时候,存在指向Activity的变量,但当退出这些Fragment之后回到Activity,然后再进入Fragment的时候,这个变量变成null
原因:Fragment在detached之后都会被reset掉,但是它并没有对ChildFragmentManager做reset,所以会造成ChildFragmentManager的状态错误
解决:我们需要在Fragment被detached的时候去重置ChildFragmentManager
@Override
public void onDetach() {
super.onDetach();
try {
Field childFragmentManager = Fragment.class
.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
在android 6.0及以后,WRITE_SETTINGS权限的保护等级已经由原来的dangerous升级为signature,这意味着我们的APP需要用系统签名或者成为系统预装软件才能够申请此权限,想要获取该权限需要提示用户跳转到修改系统的设置界面去授予此权限,同时debug模式是不能申请该权限
所以你在申请该权限时不能使用checkSelfPermissions检测WRITE_SETTINGS权限,因为它是系统权限,该方法永远返回的是false,而是通过Settings.System.canWrite(Context)检测是否拥有写入系统权限的权限,如果没有就需要引导用户去设置界面进行授权
if (!Settings.System.canWrite(MainActivity.this)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.notifyTitle);
builder.setMessage("我们的应用需要您授权\"修改系统设置\"的权限,请点击\"设置\"确认开启");
builder.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setPositiveButton(R.string.setting,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ForWrittingSetting);
}
});
builder.setCancelable(false);
builder.show();
}
保证工程和引用库文件用同一个支持包,删除build目录,clean工程
eq:第一个activity引用android.app.activity包,第二个activity引用v7包的AppcompantActivity,这样可能就会报找不到第一个activity
原因 是build.gradle文件配置了
dependencies {
compile fileTree(include: '.jar’, dir: ‘libs’)
}
这里面已经添加过jar包,但是又在混淆文件proguard.cfg里面又加了句-libraryjars libs/**.jar,
将-libraryjars libs/***.jar 前面用#号注释或者直接删掉即可。
注意:sdk 通过 proguard 混淆代码时默认已经将 lib目录中的 jar 都已经添加到打包脚本中,所以不需要再次手动添加。
这个在mainfest.xml中activity下面有一个属性为windowSoftInputMode,它共有10个值可以配置,每个配置都对页面输入法弹出框影响不同
这是因为
1,如果一端的Socket被关闭(或主动关闭,或因为异常退出而 引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。
2,一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。
简单的说就是在连接断开后的读和写操作引起的。
这是因为服务端没有启动,或者与服务端连接的端口或者ip不一致,意思就是连接不到相对应的服务端
LINUX:
telnet 10.100.20.137 7780 #查看10.100.20.137服务器的7780是否有数据发出
tcpdump udp port 11011 #是否有数据走UDP协议往端口11011发
tcpdump tcp port 8888 #是否有数据走TCP协议往端口8888发
WIN方法:
winshark
有时候在运行一些开发工具的时候经常会碰到端口被占用的情况,比如adb运行端口被其它流氓软件占用,解决如下
在开发中通常使用 + 号来将几个String进行拼接显示到XML中的TextView标签里,这显然是不合理的,可以使用getString方法进行更完美的实现
说到getString方法需要先说到三个约束符
eq1:在strings.xml中定义一个格式约束符
%1$s(%2$d/%3$d),%4$s(%5$1.1f)
可以看到这里总共是由2个String、2个整数、1个浮点数组成
接下来在代码里使用
String result = getString(R.string.format,"小明作业完成情况",8,16,"完成率",0.5);
打印出来的结果如下
小明作业完成情况(8/16),完成率(0.5)
eq2:上面的格式约束符是由纯符号组成,也可以文字加符号一起
我今年%1$d岁了,来自%2$s
这里需要使用format方法,其实你看getString源码实现,就知道最后也是调用的format方法
String age = String.format(getString(R.string.age),15,"北京");
打印结果
我今年15岁了,来自北京
eq3:如果需要文字的一部分用特殊颜色显示,可以使用html
应付: ¥%1$.2f]]>
%1$d件,合计: ¥%2$.2f 元]]>
mText.setText(Html.fromHtml(String.format(getResources().getString(R.string.pay),66.66)));
这里面的应付两个字也可以用上面的例子中的约束符替代,然后在代码里可以动态显示xxx应付,这样就更加动态化了,适应性更强
关于url下载链接中包含中文导致下载失败的问题处理方法
先用URLEncoder将整个url进行转码,但是转码后还需要将url中的 / ,: ,空格等再转回来
downUrl = URLEncoder.encode(downUrl, "utf-8");
downUrl = downUrl.replace("\\+", "%20");
downUrl = downUrl.replace("%2F", "/");
downUrl = downUrl.replace("%3A", ":");
平时开发中可能需要获取手机相关信息,比如IMEI,IMSI号,手机号等
String imei = "";
String imsi = "";
String phoneNum = "";
TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
imei = manager.getDeviceId();
imsi = manager.getSubscriberId();
phoneNum = manager.getLine1Number();
记得加上权限
< uses-permission android:name=“android.permission.READ_PHONE_STATE”/>
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
这种问题是由下面这句话导致
cursor.getColumnIndex("xxx"))
这个xxx是表里面的一个字段,报这个错是因为表里没有这个字段,然后通过cursor查询就找不到