MIUI 系统 BUG,Android 调用相机崩溃?将拍照适配方案进行到底!

本文主要是介绍MIUI 系统 BUG,Android 调用相机崩溃?将拍照适配方案进行到底!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面

昨天也是为大家分享了 7.0 相机适配,今天就来为大家讲讲 Android 之相机适配。

提起 Android 调用系统相机拍照上传图片或者是显示图片,想必任何一位开发 Android 的朋友都不会陌生,基本这个功能已经涵盖各个应用了,今天,我就来给大家聊聊网上并不多见却有经常听到大家吐槽的问题。

根据相机适配对图片的操作,所以有了这款图片压缩库:[https://github.com/nanchen2251/CompressHelper

拍照功能实现

对于拍照功能的实现方式我这里就不多谈了,无非两种,一种是利用相机的 API 来自定义相机,另一种是利用 Intent 调用系统指定的相机拍照。而这两种方式的实现网上搜索一大把,我就不在这里啰嗦了。

有没有相机可用?

前面讲到我们是调用系统指定的相机 APP 来拍照,那么系统是否存在可以被我们调用的 APP 呢?这个我们不敢确定,毕竟 Android 奇葩问题多,还真有遇到过这种极端的情况导致闪退的。虽然很极端,但作为客户端人员还是要进行处理,方式有二:

  • 调用相机时,简单粗暴的 try-catch
  • 调用相机前,检测系统有没有相机 APP 可用

try-catch 这种粗暴的方式大家肯定很熟悉了,那么要如何检测系统有没有相机 APP 可用呢?系统在 PackageManager 里为我们提供这样一个 API:


通过这样一个 API ,可以知道系统是否存在 Action 为 MediaStore.ACTION_IMAGE_CAPTURE 的 Intent 可以唤起的拍照界面,具体实现代码如下:

/*** 判断系统中是否存在可以启动的相机应用** @return 存在返回true,不存在返回false*/public boolean hasCamera() {PackageManager packageManager = mActivity.getPackageManager();Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);return list.size() > 0;}

拍出来的照片“歪了”!!!

经常会遇到一种情况,拍照时看到照片是正的,但是当我们的 APP 获取到这张照片时,却发现旋转了 90 度(也有可能是 180、270,不过 90 度比较多见,貌似都是由于手机传感器导致的)。很多童鞋对此感到很困扰,因为不是所有手机都会出现这种情况,就算会是出现这种情况的手机上,也并非每次必现。要怎么解决这个问题呢?从解决的思路上看,只要获取到照片旋转的角度,利用 Matrix 来进行角度纠正即可。那么问题来了,要怎么知道照片旋转的角度呢?细心的童鞋可能会发现,拍完一张照片去到相册点击属性查看,能看到下面这样一堆关于照片的属性数据。

img_6cc40259b0678e60e30f0c932e1856c9.png

没错,这里面就有一个旋转角度,倘若拍照后保存的成像照片文件发生了角度旋转,这个图片的属性参数就能告诉我们到底旋转了多少度。只要获取到这个角度值,我们就能进行纠正的工作了。 Android 系统提供了 ExifInterface 类来满足获取图片各个属性的操作。
img_42a59a479b4e334edd1af923424aa1f9.png

通过 ExifInterface 类拿到 TAG_ORIENTATION 属性对应的值,即为我们想要得到旋转角度。再根据利用 Matrix 进行旋转纠正即可。实现代码大致如下:

/*** 获取图片的旋转角度** @param path 图片绝对路径* @return 图片的旋转角度*/public static int getBitmapDegree(String path) {int degree = 0;try {// 从指定路径下读取图片,并获取其EXIF信息ExifInterface exifInterface = new ExifInterface(path);// 获取图片的旋转信息int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_90:degree = 90;break;case ExifInterface.ORIENTATION_ROTATE_180:degree = 180;break;case ExifInterface.ORIENTATION_ROTATE_270:degree = 270;break;}} catch (IOException e) {e.printStackTrace();}return degree;}/*** 将图片按照指定的角度进行旋转** @param bitmap 需要旋转的图片* @param degree 指定的旋转角度* @return 旋转后的图片*/public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) {// 根据旋转角度,生成旋转矩阵Matrix matrix = new Matrix();matrix.postRotate(degree);// 将原始图片按照旋转矩阵进行旋转,并得到新的图片Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);if (bitmap != null && !bitmap.isRecycled()) {bitmap.recycle();}return newBitmap;}

ExifInterface 能拿到的信息远远不止旋转角度,其他的参数感兴趣的童鞋可以看看 API 文档。

拍完照怎么闪退了?

曾在小米和魅族的某些机型上遇到过这样的问题,调用系统相机拍照,拍完点击确定回到自己的 APP 里面却莫名奇妙的闪退了。这种闪退有两个特点:
没有什么错误日志(有些机子啥日志都没有,有些机子会出来个空异常错误日志);
同个机子上非必现(有时候怎么拍都不闪退,有时候一拍就闪退);

对待非必现问题往往比较头疼,当初遇到这样的问题也是非常不解。上网搜罗了一圈也没方案,后来留意到一个比较有意思信息:有些系统厂商的 ROM 会给自带相机应用做优化,当某个 APP 通过 Intent 进入相机拍照界面时,系统会把这个 APP 当前最上层的 Activity 销毁回收。(注意:我遇到的情况是有时候很快就回收掉,有时候怎么等也不回收,没有什么必现规律)为了验证一下,便在启动相机的 Activity 中对 onDestory() 方法进行加 Log 。果不其然,终于发现进入拍照界面的时候 onDestory() 方法被执行了。所以,前面提到的闪退基本可以推测是 Activity 被回收导致某些非UI控件的成员变量为空导致的。(有些机子会报出空异常错误日志,但是有些机子闪退了什么都不报,是不是觉得很奇葩!)
既然涉及到 Activity 被回收的问题,自然要想起 onSaveInstanceState()onRestoreInstanceState() 这对方法。去到 onSaveInstanceState() 把数据保存,并在 onRestoreInstanceState() 方法中进行恢复即可。大体代码思路如下:

@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);mRestorePhotoFile = mCapturePhotoHelper.getPhoto();if (mRestorePhotoFile != null) {outState.putSerializable(EXTRA_RESTORE_PHOTO, mRestorePhotoFile);}}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);mRestorePhotoFile = (File) savedInstanceState.getSerializable(EXTRA_RESTORE_PHOTO);mCapturePhotoHelper.setPhoto(mRestorePhotoFile);}

对于 onSaveInstanceState()onRestoreInstanceState() 方法的作用还不熟悉的童鞋,网上资料很多,可以自行搜索。
到这里,可能有童鞋要问,这种闪退并不能保证复现,我要怎么知道问题所在和是否修复了呢?我们可以去到开发者选项里开启不保留活动这一项进行调试验证。

img_f6be5332fffc84ac7cf443d75ec1c3b7.png

它的作用是保留当前和用户接触的 Activity ,并将目前无法和用户交互 Activity 进行销毁回收。打开这个调试选项就可以满足验证的需求,当你的 app 的某个 Activity 跳转到拍照的 Activity 后,这个 Activity 立马就会被系统销毁回收,这样就可以很好的完全复现闪退的场景,帮助开发者确认问题有没有修复了。
涉及到 Activity 被销毁,还想提一下代码实现上的问题。假设当前有两个 Activity ,MainActivity 中有个 Button ,点击可以调用系统相机拍照并显示到 PreviewActivity 进行预览。有下面两种实现方案:

  • MainActivity 中点击 Button 后,启动系统相机拍照,并在 MainActivity 的 onActivityResult() 方法中获取拍下来的照片,并启动跳转到 PreviewActivity 界面进行效果预览;
  • MainActivity 中点击 Button 后,启动 PreviewActivity 界面,在 PreviewActivity 的 onCreate()(或者 onStart()onResume())方法中启动系统相机拍照,然后在 PreviewActivity 的 onActivityResult() 方法中获取拍下来的照片进行预览;

上面两种方案得到的实现效果是一模一样的,但是第二种方案却存在很大的问题。因为启动相机的代码放在 onCreate()(或者 onStart()onResume())中,当进入拍照界面后,PreviewActivity 随即被销毁,拍完照确认后回到 PreviewActivity 时,被销毁的 PreviewActivity 需要重建,又要走一遍 onCreate()onStart()onResume(),又调用了启动相机拍照的代码,周而复始的进入了死循环状态。为了避免让你的用户抓狂,果断明智的选择方案一。
以上这种情况提到调用系统拍照时,Activity 就回收的情况,在小米 4S 和小米 4 LTE 机子上(MIUI 的版本是 7.3,Android 系统版本是 6.0)出现的概率很高。 所以,建议看到此文的童鞋也可以去验证适配一下。

图片无法显示

图片无法显示这个问题也是略坑,如何坑法?往下看,同样是在小米 4S 和小米 4 LTE 机子上(MIUI 的版本是 7.3,Android 系统版本是 6.0)出现概率很高的场景(当然,不保证其他机子没出现过)。按照我们前面提到的业务场景,调用相机拍照完成后,我们的 APP 会有一个预览图片的界面。但是在用了小米的机子进行拍照后,自己 APP 的预览界面却怎么也无法显示出照片来,同样是相当郁闷,郁闷完后还是要一步一步去排查解决问题的!为此,需要一步一步猜测验证问题所在。

  • 猜测一:没有拿到照片路径,所以无法显示?
    直接断点打 log 跟踪,猜测一很快被推翻,路径是有的。
  • 猜测二:Bitmap太大了,无法显示?
    直接在 Android Studio 的 log 控制台仔细的观察了一下系统 log ,发现了一些蛛丝马迹
    OpenGLRenderer: Bitmap too large to be uploaded into a texture

每次拍完照片,都会出现上面这样的 log ,果然,因为图片太大而导致在 ImageView 上无法显示。到这里有童鞋要吐槽了,没对图片的采样率 inSampleSize 做处理?天地良心啊,绝对做处理了,直接看代码:

/*** 压缩Bitmap的大小** @param imagePath     图片文件路径* @param requestWidth  压缩到想要的宽度* @param requestHeight 压缩到想要的高度* @return*/public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {if (!TextUtils.isEmpty(imagePath)) {if (requestWidth <= 0 || requestHeight <= 0) {Bitmap bitmap = BitmapFactory.decodeFile(imagePath);return bitmap;}BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高BitmapFactory.decodeFile(imagePath, options);options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率options.inJustDecodeBounds = false;return BitmapFactory.decodeFile(imagePath, options);} else {return null;}}public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {final int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;Log.i(TAG, "height: " + height);Log.i(TAG, "width: " + width);if (height > reqHeight || width > reqWidth) {final int halfHeight = height / 2;final int halfWidth = width / 2;while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {inSampleSize *= 2;}long totalPixels = width * height / inSampleSize;final long totalReqPixelsCap = reqWidth * reqHeight * 2;while (totalPixels > totalReqPixelsCap) {inSampleSize *= 2;totalPixels /= 2;}}return inSampleSize;}

瞄了代码后,是不是觉得没有问题了?没错,inSampleSize 确确实实经过处理,那为什么图片还是太大而显示不出来呢? requestWidthrequestHeight 设置得太大导致 inSampleSize 太小了?不可能啊,我都试着把长宽都设置成 100 了还是没法显示!干脆,直接打印 inSampleSize 值,一打印,inSampleSize 值居然为 1 。 我去,彻底打脸了,明明说好的处理过了,居然还是 1 !!!!为了一探究竟,干脆加 log 。

public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {if (!TextUtils.isEmpty(imagePath)) {Log.i(TAG, "requestWidth: " + requestWidth);Log.i(TAG, "requestHeight: " + requestHeight);if (requestWidth <= 0 || requestHeight <= 0) {Bitmap bitmap = BitmapFactory.decodeFile(imagePath);return bitmap;}BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高BitmapFactory.decodeFile(imagePath, options);Log.i(TAG, "original height: " + options.outHeight);Log.i(TAG, "original width: " + options.outWidth);options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率Log.i(TAG, "inSampleSize: " + options.inSampleSize);options.inJustDecodeBounds = false;return BitmapFactory.decodeFile(imagePath, options);} else {return null;}}

运行打印出来的日志如下:


图片原来的宽高居然都是 -1 ,真是奇葩了!难怪, inSampleSize 经过处理之后结果还是 1 。狠狠的吐槽了之后,总是要回来解决问题的。那么,图片的宽高信息都丢失了,我去哪里找啊? 像下面这样?

public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {...BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);bitmap.getWidth();bitmap.getHeight();...} else {return null;}}

no,此方案行不通,inJustDecodeBounds = true 时,BitmapFactory 获得 Bitmap 对象是 null;
那要怎样才能获图片的宽高呢?前面提到的 ExifInterface 再次帮了我们大忙,通过它的下面两个属性即可拿到图片真正的宽高。


顺手吐槽一下,为什么高不是 TAG_IMAGE_HEIGHT 而是 TAG_IMAGE_LENGTH。改良过后的代码实现如下:

public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {if (!TextUtils.isEmpty(imagePath)) {Log.i(TAG, "requestWidth: " + requestWidth);Log.i(TAG, "requestHeight: " + requestHeight);if (requestWidth <= 0 || requestHeight <= 0) {Bitmap bitmap = BitmapFactory.decodeFile(imagePath);return bitmap;}BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高BitmapFactory.decodeFile(imagePath, options);Log.i(TAG, "original height: " + options.outHeight);Log.i(TAG, "original width: " + options.outWidth);if (options.outHeight == -1 || options.outWidth == -1) {try {ExifInterface exifInterface = new ExifInterface(imagePath);int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度Log.i(TAG, "exif height: " + height);Log.i(TAG, "exif width: " + width);options.outWidth = width;options.outHeight = height;} catch (IOException e) {e.printStackTrace();}}options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率Log.i(TAG, "inSampleSize: " + options.inSampleSize);options.inJustDecodeBounds = false;return BitmapFactory.decodeFile(imagePath, options);} else {return null;}}

再看一下,打印出来的 log


以上总结了这么些身边童鞋经常问起,但网上又不多见的适配问题,希望可以帮到一些开发童鞋少走弯路。文中多次提到小米的机子,并不代表只有MIUI上有这样的问题存在,仅仅只是因为我身边带的几部机子大都是小米的。对待适配问题,在搜索引擎都无法提供多少有效的信息时,我们只能靠断点、打 log、观察控制台的日志、以及 API 文档来寻找一些蛛丝马迹作为突破口,相信办法总比困难多。
以上内容采自:There
至于为什么基本全文 copy,是因为我觉得作者已经讲的特别清楚了,我没必要做二次重复,也只是给大家分享一下。
那下面就让我来补充一下不一样的开发情景。

如果同事写好了压缩九宫格显示图片呢?

这时候你们大框架已经搞定了,只需要你传回一个文件的path,你可能会这样写:(下面所有代码都在 onActivityResult()` 方法)

if (null != imageGridAdapter.uri) {final String url = PhotoUtil.getImageUrlFromActivityResult(this, imageGridAdapter.uri);//这个方法可以拿到图片的pathLog.e(TAG, "onActivityResult: url:" + url);if (!TextUtils.isEmpty(url)) {file = new File(url);size = file.length();Log.e(TAG, "onActivityResult: size:" + size);if (size > 0 ){ImageItem imageItem = new ImageItem();imageItem.ImageId = ImageItem.NEW_ID;imageItem.PhotoPath = url;imageGridAdapter.getmDataList().add(imageItem);imageGridAdapter.notifyDataSetChanged();imageGridAdapter.uri = null;}}
}

好像没啥问题呀,拿到图片的 path,new 一个文件,如果文件 size = 0,则不显示,大于 0 说明图片存在,则显示图片,提示 UI 刷新。
嗯,的确,绝大部分手机都测试通过了,然而在坑爹的部分MIUI系统上出现了,返回 size 为 0,进不到判断循环,自然不会显示那个图片。
这时候肯定要到 google 上去搜上一圈,一圈下来收获不少,却没找到真正解决的办法。
这里有位朋友就说啦,这个 size 为0,但是间隔一定的时间就可以 new 出 size 不为 0 的 file,而这个时间是不固定的。


img_633a13b89a8a5fe629ee81147425ba3e.png
img_21c20f231983efca7d46f2054dde65ef.png

可见遇上这个坑的小伙伴也是尽心尽力,想方设法。
所以我也尝试了这个方法,考虑到不能休眠主线程,就采用新开一个线程来延时处理,采用加载框,一旦 size 不为 0 了,才进行显示处理。
可能图片出问题,所以我们设置一个最大休眠时间。代码为:(其中 flag 和 time 为全局变量)

flag = true;time = 0;final String url = PhotoUtil.getImageUrlFromActivityResult(this,imageGridAdapter.uri);if (size <= 0) { // 如果size小于0出现了,则使用加载框new Thread(new Runnable() {@Overridepublic void run() {runOnUiThread(new Runnable() {@Overridepublic void run() {showLoading(SendQuestionActivity.this);// 该方法为显示加载框}});while (flag) {// 设置延迟步长是0.5stry {Thread.sleep(500);time += 0.5;file = null;file = new File(url);size = file.length();Log.e(TAG, "onActivityResult: size:" + size);if (size > 0 || time >= 10) {flag = false;}} catch (InterruptedException e) {e.printStackTrace();}}runOnUiThread(new Runnable() {@Overridepublic void run() {stopLoading();//该方法为取消加载框}});}}).start();}ImageItem imageItem = new ImageItem();imageItem.ImageId = ImageItem.NEW_ID;imageItem.PhotoPath = url;imageGridAdapter.getmDataList().add(imageItem);imageGridAdapter.notifyDataSetChanged();imageGridAdapter.uri = null;

这样问题是得到解决啦,但是用户取消的时候 size 也为 0 呀,这样无疑是画蛇添足,用户取消拍照都要显示加载框 10s,想想都可怕!!!

又听说在 new File 的前面加上下面的这句话可以解决,倒腾一番,然并卵。

// 小米4 LTE MIUI 7.0 版本下,file的size始终为0;通过提前获取ExifInterface信息,保证文件确实写入到外存
try {ExifInterface exifInterface = new ExifInterface(url);
} catch (Exception e) {e.printStackTrace();
}

额,等等。上面说了,ExifInterface 可以拿到图片的宽高等参数,那我是不是可以直接通过判断图片宽高是否为 0 来判断用户是否拍照呢?如果 widthheight 为 0,说明用户取消了拍照,不显示。否则显示图片,心动不如行动,直接上代码。

flag = true;
Log.e(TAG, "onActivityResult: uri:" + imageGridAdapter.uri);
if (null != imageGridAdapter.uri) {final String url = PhotoUtil.getImageUrlFromActivityResult(this,imageGridAdapter.uri);Log.e(TAG, "onActivityResult: url:" + url);boolean flag = true;// 小米4 LTE MIUI 7.0 版本下,file的size始终为0;通过提前获取ExifInterface信息,保证文件确实写入到外存try {ExifInterface exifInterface = new ExifInterface(url);int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度Log.e(TAG, "onActivityResult: height:" + height);Log.e(TAG, "onActivityResult: width:" + width);if (height == 0 && width == 0) {flag = false;}} catch (Exception e) {e.printStackTrace();}if (!TextUtils.isEmpty(url)) {file = new File(url);size = file.length();Log.e(TAG, "onActivityResult: size:" + size);/*** MIUI8.0上面方案无法解决,经测试发现在一定时间后能保证size不为0* 奇怪的发现当size为0的时候依然可以拿到图片,多款手机测试通过*/if (flag) {ImageItem imageItem = new ImageItem();imageItem.ImageId = ImageItem.NEW_ID;imageItem.PhotoPath = url;imageGridAdapter.getmDataList().add(imageItem);imageGridAdapter.notifyDataSetChanged();imageGridAdapter.uri = null;}}}

OK,终于解决了。希望能帮到大家!

做不完的开源,写不完的矫情。欢迎扫描下方二维码或者公众号搜索「nanchen」关注我的微信公众号,目前多运营 Android ,尽自己所能为你提升。如果你喜欢,为我点赞分享吧~


nanchen

这篇关于MIUI 系统 BUG,Android 调用相机崩溃?将拍照适配方案进行到底!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/297710

相关文章

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

android 带与不带logo的二维码生成

该代码基于ZXing项目,这个网上能下载得到。 定义的控件以及属性: public static final int SCAN_CODE = 1;private ImageView iv;private EditText et;private Button qr_btn,add_logo;private Bitmap logo,bitmap,bmp; //logo图标private st

Android多线程下载见解

通过for循环开启N个线程,这是多线程,但每次循环都new一个线程肯定很耗内存的。那可以改用线程池来。 就以我个人对多线程下载的理解是开启一个线程后: 1.通过HttpUrlConnection对象获取要下载文件的总长度 2.通过RandomAccessFile流对象在本地创建一个跟远程文件长度一样大小的空文件。 3.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa