赞
踩
启动页黑屏处理:
https://www.jianshu.com/p/0026a01c6811
https://www.cnblogs.com/liqw/p/4263418.html
//在根布局节点设置clipChildren=false,这个属性默认为true.意思是是否限制子视图在其范围内。
//其次就是要用layout_gravity来控制超出的部分显示位置。
android:clipChildren="false"
如:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false"> <LinearLayout android:layout_width="match_parent" android:layout_height="40dip" android:background="#B0C4DE" android:orientation="horizontal" android:layout_alignParentBottom="true"> <ImageView android:layout_width="0dip" android:layout_height="fill_parent" android:layout_weight="1.0" android:scaleType="fitCenter" android:src="@mipmap/ic_launcher" /> <ImageView android:layout_width="0dip" android:layout_height="fill_parent" android:layout_weight="1.0" android:scaleType="fitCenter" android:src="@mipmap/ic_launcher" /> <ImageView android:layout_width="0dip" android:layout_height="75dip" android:layout_gravity="bottom" android:layout_weight="1.0" android:scaleType="fitCenter" android:src="@mipmap/ic_launcher" /> <ImageView android:layout_width="0dip" android:layout_height="fill_parent" android:layout_weight="1.0" android:scaleType="fitCenter" android:src="@mipmap/ic_launcher" /> <ImageView android:layout_width="0dip" android:layout_height="fill_parent" android:layout_weight="1.0" android:scaleType="fitCenter" android:src="@mipmap/ic_launcher" /> </LinearLayout>
【比重】: https://www.cnblogs.com/net168/p/4227144.html
StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
//1.去除字符串换行符
s=s.replaceAll("\r|\n","");
//方法2
public static String replaceBlank(String str) {
String dest = "";
if (str!=null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
从Android API Level 23(Android 6.0)开始,不能再在Android中使用DefaultHttpClient,强制使用HttpURLConnection。
一般情况下,URL的长度不能超过2048个字符,即2KB,超过此限制的话服务器可能就不识别。
URL的最大长度就是2048个字符,如果我们发送的数据很大,超过了2KB怎么办?我们可以将很大的数据放到请求体中,GET请求不支持请求体,只有POST请求才能设置请求体。
https://blog.csdn.net/iispring/article/details/51474529
Intent传递数据大小的限制大概在1M左右,超过这个限制就会静默崩溃。
一般是xml错误,或者在类继承时导入错误的包
因为Kotlin在编译时不检查导入的包的错误
在Dagger中CashLoan中全部写在一个ActivityComponent中,是因为只有一个Module,如果是多模块的Module则最好用多个ActivityComponent
v4 v7重复依赖问题深究
compile('com.facebook.fresco:fresco:0.10.0') {
exclude module: 'support-v4'
}
//如果是源码形式引入的开源库:
compile (project(':thirdpart:RecyclerViewAdapterLibrary')){
exclude group: 'com.android.support'
}
【ARouter::Compiler >>> No module name, for more information, look at gradle log.】
由于ARouter版本原因错误
// 替换成最新版本, 需要注意的是api
// 要与compiler匹配使用,均使用最新版可以保证兼容
compile 'com.alibaba:arouter-api:x.x.x'
annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
annotationProcessor "com.alibaba:arouter-compiler:1.1.4"
api "com.alibaba:arouter-api:1.3.1"
ARouter.getInstance()
.build(RouterPath.UserCenter.PATH_LOGIN)
.withFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
.withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.navigation()
https://www.cnblogs.com/baiqiantao/p/10125084.html
1.在清单Application节点下:tools:replace=“label,icon,theme” (可以不要)
2. manifestPlaceholders = [
GETUI_APP_ID : “APP_ID”,
GETUI_APP_KEY : “APP_KEY”,
GETUI_APP_SECRET : “APP_SECRET”
]
所以:引用某个库时,一定要按库(sdk)配置好才build。
报xml等错误:原因
1)布局中引入的是sdk的布局还是Android.widget的(可能性小)
2)清单中没有添加<meta…>宽高等
都要有
//ARouter
annotationProcessor "com.alibaba:arouter-compiler:$arouter_compiler_version"
和(否则报错–且错误中有提示)
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
RecyclerView 去掉滑动边缘阴影效果android:overScrollMode=“never”
LinearLayoutManager不能多个RecyclerView公用
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(mContext) { @Override public boolean canScrollVertically() { return false; } }; ----设置RecyclerView滑动监听----- //只适用于NestedScrollingChild的子类,就是RV外层是Nest... //recyclerView.setNestedScrollingEnabled(false); //app:reverseLayout="true" //是否从右到左布局 LayoutManager的滑动方法 scrollToPositionWithOffset(int position, int offset) setSmoothScrollbarEnabled(boolean) RecyclerView提供了几种移动的方法 scrollToPosition (直接闪现至某一位位置) scrollTo scrollBy smoothScrollBy smoothScrollToPosition (惯性滑动至某一位置)
//继承XXXLayoutManager,重写canScrollXXX, public class MyLinearLayoutManager extends LinearLayoutManager { private boolean canScroll = true; public MyLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public MyLinearLayoutManager(Context context, int spanCount) { super(context, spanCount); } public MyLinearLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { super(context, spanCount, orientation, reverseLayout); } @Override public boolean canScrollVertically() { return canScroll && super.canScrollVertically(); } @Override public boolean canScrollHorizontally() { return super.canScrollHorizontally(); } /** * 设置是否可以滑动 */ public void setCanScroll(boolean canScroll) { this.canScroll = canScroll; } }
Drawable drawableLeft = getResources().getDrawable(R.mipmap.weixin_pay);
//img.setBounds(0, 0, img.getMinimumWidth(), img.getMinimumHeight());
tvEnd.setCompoundDrawablePadding(20);
textView.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, null, null);
获取应用程序最高可用内存
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
Log.d("TAG", "Max memory is " + maxMemory + "KB");
0.根据图片来源,选择BitmapFactory的解析方法
1.禁止为Bitmap分配内存
2.获取图片长宽高和MIME
3.计算合适的inSampleSize(压缩比例)
4.再次解析
style="?android:attr/borderlessButtonStyle"
或者在styles里parent="@style/Widget.AppCompat.Button.Borderless"
但是点击没有样式效果了
去除button大写字母:android:textAllCaps=“false”
去除背景色view.setBackgroundResource(0);
在Item的背景添加
android:background="?android:attr/selectableItemBackground"
【】
editText、checkBox在列表中直接使用是有问题的
如果非要使用,给他们设置tag
状态栏:24dp,标题栏:48dp,或者?android:attr/actionBarSize,底部导航栏:56dp
clipChildren:false—是否限制子View在其范围内,默认的时候是true
android:divider="@drawable/gray_line"
android:showDividers="end"
NumberFormatException: Invalid int: “25.0”
字符串在转数据类型时,如float等,最好添加try catch ,否则在第一次输入 . 时崩掉
RL.setBackgroundResource(R.color/drawable.color_white)//直接用此,
//不要用getResource.getColor()
RL.setBackgroundResource(getResource.getColor(R.color.color_white))//崩掉
(1)RelativeLayout慢于LinearLayout是因为它会让子View调用2次measure过程,而后者只需一次,但是有weight属性存在时,后者同样会进行两次measure。
(2)RelativeLayout的子View如果高度和RelativeLayout不同,会引发效率问题,可以使用padding代替margin以优化此问题。
(3)在不响应层级深度的情况下,使用Linearlayout而不是RelativeLayout。
采用RelativeLayout并不会降低层级深度,因此这种情况下使用LinearLayout效率更高。
为开发者默认新建RelativeLayout是希望开发者能采用尽量少的View层级,很多效果是需要多层LinearLayout的嵌套,这必然不如一层的RelativeLayout性能更好。因此我们应该尽量减少布局嵌套,减少层级结构,使用比如viewStub,include等技巧。
现在也基本是用 ConstraintLayout
https://segmentfault.com/q/1010000008022583
https://developer.android.com/training/articles/perf-tips#internal_get_set
https://www.jianshu.com/p/c73041a62111
1、LinkedList插入删除相对较快,而查询较慢;
2、ArrayList插入删除相对较慢,而查询很快(详细可查看从源码的角度分析List与Set的区别);
卸载时,应用的SharedPreferences文件会被删除,而当覆盖安装时,则会被保留。因此,想要对不同版本区分,可以尝试key+version的方式。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 创建和删除文件 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!--安装包时需要-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!--常用的-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
private void requestPermission() { boolean isGranted = true; //23是6.0(以后需要动态申请) if (Build.VERSION.SDK_INT >= 23) { if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //如果没有写sd卡权限 isGranted = false; } if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { isGranted = false; } if (!isGranted) { this.requestPermissions( new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 7); } else { //以后每次授予权限后的逻辑 //startDown(); } } else { //小于6.0的权限直接再清单里就行 //startDown(); } }
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //读写文件--安装apk if (requestCode == 7) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { //第一次授予权限后的逻辑 //startDown(); } else { // Permission Denied的逻辑 //startDown(); } return; } if (requestCode == Config.CODE_CAMERA) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { openCamera(); } else { // Permission Denied // Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show(); } return; } if (requestCode == Config.CODE_MULTI_PERMISSION) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { operAlbum(); // startActivityForResult(new Intent(this, ScanActivity.class),Config.QRCODE_REQUESTCODE); //拨打电话 } else { // Permission Denied // Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show(); } return; } super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
//再res下新建xml文件夹,创建filepaths.xml文件(名字自定义),如下: <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!--Android7.0调用相机,用于指定共享的目录--> <external-path name="image" path="." /> <external-path name="files_root" path="."/> <!--external-path 表示用来指定共享路径的--> <!--name 随便取,只是一个标签--> <!--path 这个比较重要,如果不设置,则表示将整个 SD 卡进行共享,然后制定了,比如 path=”Pictrues”那么,就只共享 sd卡下的 Pictures 文件夹--> </paths>
<application>
。。。
<provider
android:name="androidx.core.content.FileProvider" //AndroidX用此
android:name="android.support.v4.content.FileProvider"
<!--这里权限自定义但唯一,后面要用到-->
android:authorities="com.zxx.utils.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
<!--这里就是上面的文件-->
android:resource="@xml/filepaths" />
</provider>
</application>
//4. 当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。 @Override protected void onPostExecute(File result) { if (result != null) { // Intent broadcast = new Intent(Constants.INTENT_ACTION_UPDATE_FINISHED); // sendBroadcast(broadcast); Intent intent = new Intent(Intent.ACTION_VIEW); //如果在Android7.0以上,使用FileProvider获取Uri if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //这里就用到了上面的权限 Uri uri = FileProvider.getUriForFile(context, "com.zxx.utils.fileprovider", file); intent.setDataAndType(uri, "application/vnd.android.package-archive"); } else { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.fromFile(result), "application/vnd.android.package-archive"); } //跳转到安装界面 startActivity(intent); } } //至此安装完成
public void openCamera() { //用于保存调用相机拍照后所生成的文件 File cameraPath = new File(Environment.getExternalStorageDirectory().getPath(), System.currentTimeMillis() + ".jpg"); ZLog.e("cameraPath=" + cameraPath.toString()); //跳转到调用系统相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //如果在Android7.0以上,使用FileProvider获取Uri if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); //这里就用到了上面的权限 Uri uri = FileProvider.getUriForFile(context, "com.zxx.utils.fileprovider", cameraPath); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } else { // 把文件地址转换成Uri格式 //否则使用Uri.fromFile(file)方法获取Uri intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraPath)); ZLog.e("Tag--99" + cameraPath.toString()); } setCameraPath(cameraPath); //添加 ((Activity) context).startActivityForResult(intent, Config.CAMERA_REQUESTCODE); }
public void operAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
//根据版本号不同使用不同的Action:http://blog.csdn.net/nbalichaoq/article/details/51992151
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
intent.setAction(Intent.ACTION_GET_CONTENT);//返回的Uri类型可以是content:// ;file:// ;http://中的一种(适配小米)
// } else {
// intent.setAction(Intent.ACTION_OPEN_DOCUMENT);//此处对小米手机没有用,只有content://一种
// }
((Activity) context).startActivityForResult(Intent.createChooser(intent, null) , Config.ALBUM_REQUESTCODE) ;
// ((Activity) context).startActivityForResult(intent, Config.ALBUM_REQUESTCODE);
}
String Setting.SEVEN_URI===就是上面的权限 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { case Config.CAMERA_REQUESTCODE: //开启相机 //用相机返回的照片去调用剪裁也需要对Uri进行处理(Android7.0) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Uri uri = FileProvider.getUriForFile(this,Setting.SEVEN_URI , cameraPath); ImageDisplayer.cropPhoto(this, uri); ZLog.e("Android在7.0以上"); } else { ImageDisplayer.cropPhoto(this, Uri.fromFile(cameraPath)); ZLog.e("Android在7.0以下"); } break; case Config.ALBUM_REQUESTCODE: //打开相册 if (data != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { ImageDisplayer.handleImgeOnKitKat(this, data); //7.0 content开头 } else { Uri uri = data.getData(); ZLog.e("uri=intent.getData :" + uri); ImageDisplayer.cropPhoto(this, uri); } } break; case Config.CROP_REQUEST_CODE: //裁剪完的图片 Bundle bundle = data.getExtras(); if (bundle != null) { //在这里获得了剪裁后的Bitmap对象,可以用于上传 Bitmap cropBitmap = bundle.getParcelable("data"); //对得到的Bitmap进行尺寸缩放 Bitmap cutBitmap = new ImageDisplayer(100, 100) .autoResizeFromBitmap(cropBitmap); //存储到本地 String filePath = controller.saveBitmap(cutBitmap); ZLog.e("filePath=" + filePath); } break; case Config.QRCODE_REQUESTCODE: //二维码 Log.e("Tag", "扫描的结果为:" + data.getStringExtra("result")); break; } } }
//Uri不同,自动下载安装 private void installApk(File file) { if (!file.exists()) { return; } Uri uri = null; Intent install = new Intent(Intent.ACTION_VIEW); install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //AUTHORITY_TAG 即为 provider 注册中的 android:authorities 值。 uri = FileProvider.getUriForFile(mContext, AUTHORITY_TAG, file); // 给目标应用一个临时授权 install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else { uri = Uri.fromFile(file); } install.setDataAndType(uri, "application/vnd.android.package-archive"); mContext.startActivity(install); } android 8.0开始 增加了安装未知权限的限制,于是需要在 mainfast.xml中添加安装未知应用的权限: <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
https://blog.csdn.net/juhua2012/article/details/79671112
应用里面包含有ContentProvider 或者 FileProvider等等其他的的provider的使用,那么就动态获取applicationId。
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config } debug { applicationIdSuffix '.debug' //增加包名后缀 } } //比较全 看wms项目 buildTypes { debug { buildConfigField("boolean", "LOG_DEBUG", "true") minifyEnabled false resValue 'string', 'app_name', 'WMS测试' applicationIdSuffix '.debug' //增加包名后缀 buildConfigField 'String', "SERVER_URL", '"http://192.168.0.4:9214/app/"' // buildConfigField 'String', "SERVER_URL", '"http://192.168.0.212:9214/app/"' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 不移除无用的resource文件 } debugbeta { debuggable = true buildConfigField("boolean", "LOG_DEBUG", "true") minifyEnabled false resValue 'string', 'app_name', 'WMS_Beta' applicationIdSuffix '.debugbeta' //增加包名后缀 buildConfigField 'String', "SERVER_URL", '"http://192.168.0.212:9214/app/"' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 不移除无用的resource文件 signingConfig signingConfigs.release } release { buildConfigField("boolean", "LOG_DEBUG", "false") minifyEnabled false resValue 'string', 'app_name', 'WMS' buildConfigField 'String', "SERVER_URL", '"http://正室地址/"' applicationIdSuffix '.release' //增加包名后缀 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 移除无用的resource文件 signingConfig signingConfigs.release } }
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider" /> </provider> Uri imageUri=null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ imageUri = FileProvider.getUriForFile(MyActivity.this,getApplication().getPackageName()+".fileprovider",outputImage); }else { imageUri = Uri.fromFile(outputImage); }
第一种是直接跳转到拨打电话界面,并将电话号码带过去,这里不需要申请权限,就可以直接跳转到拨号界面
Intent intent = new Intent(Intent.ACTION_DIAL);
Uri data = Uri.parse("tel:" + "135xxxxxxxx");
intent.setData(data);
startActivity(intent);
第二种是直接播出电话,需要在AndroidManifest文件中加这个权限,如果api>=23还需要申请动态权限
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + "135xxxxxxxx");
intent.setData(data);
startActivity(intent);
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
//所以
清单:android:launchModel = "singleTask"
如果intent对象包含FLAG_ACTIVITY_CLEAR_TOP 标记,当目标task中已存在与接收该intent对象的 activity类型相同的activity实例存在时,所有位于该activity对象上面的activity将被清空,这样接收该intent的 activity就位于栈顶,可以响应到来的intent对象。
如果目标activity的运行模式为standard(默认),则目标activtiy也会被清空。因为当运行模式为standard时,总会创建新的activity对象来接收到来的intent对象。
//或者:清单:
android:launchModel = "singleTask"
Intent intent= new Intent(this, 首页Activity.class);
startActivity(intent);
Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
清单:android:launchModel = "singleTask"
//用Clear_Top是清除 LoginActivity之上的Activity
A-B-Login-D-E:从E跳转到Login则DE清除,AB还在
adb
adb devices //列出所有设备
adb kill-server //杀死所有adb服务
adb start-server //重启adb服务
gradle dependencies
cd .. //返回上级目录
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。