Android 国际化与本地化探索

2024-05-26 17:08

本文主要是介绍Android 国际化与本地化探索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android 国际化与本地化探索

    • 1、翻译注意事项
      • 1.1、尽量避免使用简写!
      • 1.2、严禁回车、换行等!
      • 1.3、尽量避免使用&、’、”等特殊符号!
      • 1.4、注意空格的使用!
    • 2、设计探讨事项
      • 2.1、标题栏
      • 2.2、输入框
      • 2.3、标签栏
      • 2.4、状态视图
      • 2.5、其他
    • 3、代码设计规范
      • 3.0、支持国际化和本地化
      • 3.1、XML相关规范
        • 3.1.1、代码规范
        • 3.1.2、TextView
        • 3.1.3、EditText
        • 3.1.4、ImageView
        • 3.1.5、自定义Shape
        • 3.1.6、不支持RTL的控件
      • 3.2、Java相关规范
        • 3.2.1、代码规范
        • 3.2.2、自定义View位置
        • 3.2.3、Throwable、Exception
        • 3.2.4、Toast
        • 3.2.5、文字格式化
      • 3.3、固定方向
    • 参考文档

缘起公司项目国际化与本地化的需求,本篇文章将从 语言翻译UI设计代码规范 ,这三个方面来进行阐述,其中不免包含本人的主观偏见,如果有任何宝贵的意见,欢迎指正。

1、翻译注意事项

由于我们现在使用的是 腾讯文档 协同处理的翻译文本,而腾讯文档导出后的Excel文件会有些奇怪的小问题,比如说标红文字前后的空格导出后空格会丢失,导致英语等其他语言显示异常。

同时,这么多的文字,加上多达十几种语言的处理,靠人工来转换成App所需资源实在是效率低下,所以脚本工程请参见:http://192.168.1.28:8888/dragon/ExcelProcessor。该工程会根据Excel文件转换为Android和iOS所需的多语言资源,具体使用方式如有需要请参阅项目README文档及源码注释。

在项目中有些文字是不确定的,需要根据情况动态改变。例如说:“小时之前”,这个,是会根据你当前时间自动计算的,现在看是“1小时之前”,那么1小时后再看就是“2小时之前”了,所以我们需要一个占位符来表示这个几,Android中会选择使用 %s ,或者 %d ,也就是 %d小时之前 。那么翻译的时候这个%d就要留出来不翻译了,我们可以考虑提供该段文字的语境,这样让翻译人员也不会一头雾水到底要怎么翻译“小时之前”了。

还有一些特殊的字符,例如英文单引号(’)、And符号(&)、英文双引号("),这些在资源文件中都有特殊含义,所以建议尽量少使用这些符号来进行翻译,如果使用了也无伤大雅,上述脚本工程会自动转义掉这些特殊符号。

一份合格、标准的多语言文档真的相当重要,所以概述注意事项如下。

1.1、尽量避免使用简写!

例如:距离通话结束还剩30秒。

错误示例:距离通话结束还剩30s。

1.2、严禁回车、换行等!

例如:1、这是第1条内容。\n\n2、这是第2条内容。

错误翻译:

  1. This is the first content. \n\n
  2. This is the second content.(iOS上会使用原格式,导致多换行)

正确翻译:1. This is the first content. \n\n2. This is the second content.

1.3、尽量避免使用&、’、”等特殊符号!

例如:建议和反馈

错误翻译:suggestions & feedback(单引号、双引号、And符号都有特殊含义)
正确翻译:suggestions and feedback

1.4、注意空格的使用!

例如:%s天之前

错误翻译:%sdays ago(英语、俄罗斯语、阿拉伯语等需要有空格)
正确翻译:%s days ago(中文、日语等不需要空格)

2、设计探讨事项

此处的设计包括了需求设计和UI设计两方面,直接来看几个实例吧!

2.1、标题栏

关于标题栏,如下图这种设计,左边返回按钮,中间标题区域,右侧子标题。这种设计有个问题就是当换用其他语言,例如俄罗斯语、马来语等,这种语言长度会很长,容易导致标题栏和子标题栏遮挡或者显示不全等问题。

在这里插入图片描述
当把右侧的文字标题设计为能明确表示意义的图标后,右侧区域长度完全可控了,至于标题换成其他语言后长度过长的问题,可能还是需要使用省略号等来进行处理。或者根据文字长度设置动态改变其大小。

在这里插入图片描述
下面的这种设计标题靠近返回按钮,也可采用,具体看App的设计了。但是第一种的设计建议千万不要采用。

在这里插入图片描述

2.2、输入框

关于输入框,一般在设计的时候可能会有如下第一种设计,文字类似这样:【群组名:请输入群组的名称】。中文情况下没有问题,因为文字大部分情况下都不会很长,UI基本无需适配。而换用俄罗斯语后,上述文字翻译后的长度会将UI完全挤变形,或者根本无法完全展示其提示信息。
在这里插入图片描述
我们可以考虑输入框中直接展示【群组名】,这样就表明这个输入框输入的是一个群组名了,省去“请输入群组的名称”这样的提示信息,这样的处理多了,还能省下一笔翻译费用。

在这里插入图片描述
实在需要提示语,那么建议采用上下的设计,如下图,这样保证上下两行文字不会互相影响,以免造成横向上排列不开的问题,这种情况下就算翻译后提示语过长,也可以换行处理,不会特别影响UI的显示效果(目前Google的Material设计输入框的默认效果就类似这样)。

在这里插入图片描述

2.3、标签栏

如下标签栏,一般我们可能会展示用户的排行榜,日榜、周榜、月榜,然后就这样居中均分设计了三个Tab标签,但是在翻译成其他语言后,可能【日榜】的翻译可能就占了大半屏幕,这样的话UI效果就大打折扣了。

在这里插入图片描述
我们可以考虑从左到右进行设计布局,如果需求之后添加【年榜】,那么我们可以直接布局到最右侧,当tab标签长度过长的时候,甚至可以让Tab横向滚动展示,这样可以最佳的去适配任何语言。

在这里插入图片描述

2.4、状态视图

如下,例如我们经常可能需要展示一些用户的状态信息,例如设计了如下在线状态,将状态信息展示在了用户昵称后。由于用户昵称本身长短不一,多语言情况下翻译后的状态信息文字也长短不一,虽然状态信息很详细的展示了出来,这样的显示效果其实很差,昵称和状态信息肯定会比较拥挤。

在这里插入图片描述
所以我们是否可以考虑使用表示状态的各色的点,来代替“在线”、“online”这种具体的文字呢?采用下图的设计显示效果就完全可控了,唯一的缺点就是颜色点无法让用户准确的理解到底是什么状态,可能需要培养一段时间的用户习惯。

在这里插入图片描述

还有的情况下,用户离线了我们可能会展示离线时间,这种翻译出来后也是长短不一,所以是否可以考虑如下的纵向设计,而不是将其显示在屏幕的最右侧。

在这里插入图片描述

2.5、其他

总之目前就一条:慎用横向排列的组件设计,横向空间有限,竖向可以无限的滚动。如果一个普通用户信息列表页面,既要用户横向滚动,又需要纵向滚动才能展示完全信息,那这个页面的用户使用率肯定大打折扣了!

3、代码设计规范

3.0、支持国际化和本地化

首先android支持切换多种语言,只需在资源文件夹中新建对应语言的values-xx文件夹,然后保证strings.xml中的字符串资源一一对应即可。
在这里插入图片描述
Android Studio为我们提供了很方便的方式,新建资源文件夹,然后在可选的限定符内选择相关内容即可,如上图所示,可以创建支持阿拉伯语的values-ar资源文件夹。

然后还需要注意的一点就是,阿拉伯语是从右向左的,也就是RTL。如果要适配阿拉伯语,在app的清单文件中声明支持RTL即可,剩下的就是布局中的适配了,请继续重点阅读下文:

android:supportsRtl="true"

如果我们需要进行app内手动更换语言,那么直接配置相关的Local即可,注意7.0前后版本的适配问题即可,如下,直接定义了切换为阿拉伯语(ar)。

public static Context attachBaseContext(Context context) {String language = getCurrentLanguage();Resources resources = context.getResources();Configuration configuration = resources.getConfiguration();Locale locale = new Locale(language);mLocale = locale;Locale.setDefault(locale);//注意7.0以上的处理方式if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {configuration.setLocales(new LocaleList(locale));return context.createConfigurationContext(configuration);} else {configuration.setLocale(locale);configuration.locale = locale;resources.updateConfiguration(configuration, resources.getDisplayMetrics());return context;}
}

然后7.0以上重写Activity的attachBaseContext(Context newBase)即可:

@Override
protected void attachBaseContext(Context newBase) {super.attachBaseContext(LanguageUtil.attachBaseContext(newBase));
}

但是在7.0及以下的手机需要在ActivityonCreate()中setContentView()之前调用:

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//7.0及以下手机还需要在这里进行处理LanguageUtil.attachBaseContext(this);setContentView(R.layout.activity_main);
}

3.1、XML相关规范

这里的代码规范我们以阿拉伯语为例来展示RTL这种XML布局方式。
(注意:相关代码仅展示了必须的属性,并非完整代码。)

3.1.1、代码规范

之前大家可能没有注意到过以下这些属性的区别,我们也是习惯了直接去书写控件的left和right属性,这在开发国内的App的时候完全没有问题,但是只要适配RTL布局,那么这就是灾难了(夸张的手法)。

所以按照Google推荐的方式,我们可以使用start和end属性来替代left、right。由于我们现在适配一般都是从Android 5.0甚至更高版本开始的,所以也无需考虑start和end在低版本系统上的兼容性了。

仅支持LTR的属性支持LTR、RTL的属性
android:gravity=“left”android:gravity=“start”
android:gravity=“right”android:gravity=“end”
android:layout_gravity=“left”android:layout_gravity=“start”
android:layout_gravity=“right”android:layout_gravity=“end”
android:paddingLeftandroid:paddingStart
android:paddingRightandroid:paddingEnd
android:drawableLeftandroid:drawableStart
android:drawableRightandroid:drawableEnd
android:layout_alignLeftandroid:layout_alignStart
android:layout_alignRightandroid:layout_alignEnd
android:layout_marginLeftandroid:layout_marginStart
android:layout_marginRightandroid:layout_marginEnd
android:layout_alignParentLeftandroid:layout_alignParentStart
android:layout_alignParentRightandroid:layout_alignParentEnd
android:layout_toLeftOfandroid:layout_toStartOf
android:layout_toRightOfandroid:layout_toEndOf
app:layout_constraintLeft_toLeftOfapp:layout_constraintStart_toStartOf
app:layout_constraintLeft_toRightOfapp:layout_constraintStart_toEndOf
app:layout_constraintRight_toRightOfapp:layout_constraintEnd_toEndOf
app:layout_constraintRight_toLeftOfapp:layout_constraintEnd_toStartOf

强烈建议以后的xml的开发规范全部按照右侧方式书写,无论是否需要适配RTL布局,这样的写法无疑是最优解!

目前项目中的可以全局替换处理,也可以使用AS提供的工具,点击Refactor->Add RTL Support Where Possible,然后运行即可。

3.1.2、TextView

当TextView中设置的文本会根据语言环境自行切换时,按照正常的TextView去设置gravity = "start"属性没有问题。LTR的布局会自行从左向右展示,RTL的布局会自行从右向左展示。

但是,在显示不本地化处理的文字时,情况就不对了,如下代码,在阿拉伯语的环境下,需要显示中文:

<TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="这是一段不本地化处理的示例文本"/>

来看下中文环境下的渲染结果:

在这里插入图片描述
然后切换到阿拉伯语环境,效果如下所示:

在这里插入图片描述

所以你看出来问题了吗?不本地化处理的文本还是按照它自己的中文环境进行了处理,即从左到右展示。但是这时候测试发难了,切换到阿拉伯语时候不应该从右到左展示吗,那不应该右对齐吗,你这样的布局也太难看了,改改吧!

没问题,加一行代码设置下TextView的对齐方式就好:

android:textAlignment="viewStart"

textAlignment属性支持的有:inherit、gravity、textStart、textEnd、center、viewStart、viewEnd。我们就看下viewStart的含义:

Align to the start of the view, which is ALIGN_LEFT if the view’s resolved layoutDirection is LTR, and ALIGN_RIGHT otherwise.

也就是说当设置了这个属性时,文本的布局会对齐到视图开始的部分,如果视图是LTR,那么对齐到左侧。否则对齐到右侧。所以再来看下设置后的渲染效果:

在这里插入图片描述

到这里相信各位小伙伴肯定对这个属性留下了深深的印象。但是,难道我们要给代码中的所有TextView手动添加这行代码吗?这也太累了吧,想偷懒!

我想说:可以!大家对style肯定不陌生吧,我们定义一个通用的TextView的style,设置它的textAlignment属性,然后在App的主题style中应用这个通用的style,自定义TextView的style代码很简单:

<style name="Text.Alignment" parent="@android:style/Widget.TextView"><item name="android:textAlignment">viewStart</item>
</style>

添加到你自己App的主题中去,记得是android:textViewStyle而不是android:textStyle,两个含义不一样哦:

<style name="AppTheme" parent="Theme.MaterialComponents.NoActionBar"><item name="android:textViewStyle">@style/Text.Alignment</item>
</style>

但是还有些文本是需要居中显示的,那你要单独再进行处理了,至于全局处理还是单个处理,请自行斟酌。

3.1.3、EditText

输入框和上述TextView也有同样的问题,按照上述方法自定义style即可,最后添加到自己App主题的时候记得属性是editTextStyle:

<item name="editTextStyle">@style/EditTextStyle.Alignment</item>

你以为这就解决问题了吗?是的,其实大部分问题都解决了,但是在部分vivo的手机上输入时候居然有半个光标的情况,如下所示:

在这里插入图片描述
起初测试直接给提了个bug,我也以为是个bug,后来多次尝试才觉得:这可能是vivo这个机型对阿拉伯语环境的“优化”?因为输入纯数字的时候EditeText无法判断这个到底是阿拉伯语还是其他语言,所以展示前后两个光标。当继续输入英文字符后,此时光标变为一个,位于英文字符之后。干脆回复测试:不予处理!!!

【请仔细阅读下文,思考为何会出现这种情况,且如何解决】

3.1.4、ImageView

关于ImageView其实在于RTL布局需不需要镜像的问题,这个问题说简单也简单说复杂也可以做的很复杂,我们先说最最最简单的方法。

  • 1、scaleX属性(推荐)

首先了解下scaleX属性,这个属性我们一般来处理X轴方向上视图的缩放,大于1时放大,小于1时缩小,那么小于0的时候呢?一开始的时候我从来没想过,但是国际化的时候翻阅官网各种镜像View的资料【见这里】,很神奇的就发现了这么个方式:

android:scaleX="-1"

X轴方向缩放到负值的时候,居然就是水平方向上的镜像效果了,牛批牛批,真的长见识了!!!(那么竖直方向的镜像效果你也应该知道怎么设置了,但是RTL布局不需要竖直方向上的镜像效果,不要多此一举哦)

正常LTR布局效果如下所示:

在这里插入图片描述
当设置以上属性的时候,布局效果如下所示,水平镜像:

在这里插入图片描述
关于是否需要ImageView的镜像效果,看你具体的图片了,以上图片只是为了演示镜像效果选择的,其实这个图片不需要镜像效果,因为上面有非本地化的文字显示,镜像之后反而不合适了。

好的,知道了怎么镜像图片,那么我们怎么根据语言环境设置相应的值呢,可以根据RTL的规范,我们在values文件夹同级目录建立values-ldrtl资源文件夹,这就表示RTL布局会使用该资源文件夹下的资源,然后建立integer.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources><integer name="rtl_scale_x">-1</integer>
</resources>

同样,在values文件夹下也需要建立integer.xml文件,内容同上述xml代码类似,值需要改为1。

然后给ImageView设置应用如下属性值即可,表示在LTR布局中水平缩放是1,也就是正常显示原图片,在RTL布局中则会镜像图片进行显示:

android:scaleX="@integer/rtl_scale_x"
  • 2、rotation属性

说完了以上最简单的方法,我们再来说一个属性,rotation,这个属性是控制视图的旋转属性的,默认是0,当我们设置:

android:rotation="180"

此时效果图如下所示:

在这里插入图片描述
这个效果并不符合我们的预期,因为它还上下颠倒了。但是有些图片,比如我们上文演示的返回按钮,它旋转180度之后显示效果是跟我们预期相符的。

  • 3、rtl文件夹

再来一种方式,根据不同的资源文件夹,放置多种方向的图片,这种方式无疑会增加APK的体积(使用bundle的方式不受影响)。

针对所有RTL设置,则命名方式为:
• drawable -> drawable-ldrtl
• drawable-xhdpi -> drawable-ldrtl-xhdpi

如果只适配阿拉伯语这么一种语言,那么也可以是这样:
• drawable-xhdpi -> drawable-ar-xhdpi

同理drawable、values、layout等资源文件夹都可以如法炮制。

3.1.5、自定义Shape

我们一般自定义shape属性如下所示:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><cornersandroid:bottomLeftRadius="20dp"android:topLeftRadius="20dp" /><gradientandroid:angle="0"android:endColor="@color/mainColorEnd"android:startColor="@color/mainColorStart" />
</shape>

效果如下所示:

在这里插入图片描述
此时处理方法也可以类似上文的ImageView一样,给使用该Shape的View设置scaleX来做镜像处理,这样做最简便。

如果想在shape中直接处理的话,部分是可以的,但是还有点限制。
先看gradient属性,它支持设置angle,0表示从左到右,180则表示从右到左,所以可以根据上文一样,使用不同的integer.xml中的值进行处理。

但是corners这个属性只支持bottomLeftRadius、topLeftRadius,并不支持bottomStartRadius、topStartRadius,所以我们无法直接在该shape文件中处理。只能建立drawable-ldrtl文件夹,建立同名文件,然后修改bottomLeftRadius、topLeftRadius为bottomRightRadius、topRightRadius进行处理了。

3.1.6、不支持RTL的控件

目前ViewPager不支持RTL的布局方向,由于时间紧任务重,本项目中还未适配该组件,可以参考GitHub上的项目 RtlViewPager 进行处理,该项目已经5年未维护了,参考下原理即可。
同时建议使用ViewPager2逐步替换ViewPager。
TabLayout现在已经支持。

3.2、Java相关规范

最重要的一点:禁止任何形式的字符串硬编码!!!

3.2.1、代码规范

同xml一样,自定义View的时候也需要注意相关left、right的问题,其他未标明的也需要自己多注意:

仅支持LTR的属性支持LTR、RTL的属性
leftMarginsetMarginStart()
rightMarginsetMarginEnd()
setMargins(int left, int top, int right, int bottom)需自行处理left、right
setPadding(int left, int top, int right, int bottom)setPaddingRelative(int start, int top, int end, int bottom)
3.2.2、自定义View位置

由于自定义View的时候可能会使用到位置属性,而layoutParams中没有Start、End这种属性,只有Left、Right。所以当我们布局视图的位置时就要考虑到RTL和LTR布局了。

比如说:视频通话页面,LTR环境下是,默认远端视频是全屏展示的,自己的视频会显示在右上角。而到了RTL环境下,那么自己的视频就需要显示在左上角了。所以定位自己视频的位置时候就需要根据不同的环境进行处理。默认情况下我们计算出正常LTR布局下小视频流的中心位置,然后判断当前的布局环境,如下所示:

Configuration config = getResources().getConfiguration();
if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {mSmallCenterX = ScreenUtils.getScreenWidth() - mSmallCenterX;
}

如果是RTL布局环境,那么镜像下处理方式就是:屏幕宽度减去LTR布局下的X坐标的位置。

然后在切换本地视图和远端视图大小的时候,动画效果也可以正常执行了。

3.2.3、Throwable、Exception

一般项目中我们会有些自定义的异常等信息,所以经常会直接使用其构造函数直接硬编码message参数。在国际化项目中建议一开始就先定制基类,传递String资源ID进去。对于一些三方框架可能也要做下兼容处理,例如如下BaseException:

public class BaseException extends Exception {private final int strId;private final int errorCode;/*** 建议使用资源ID的方式*/public BaseException(int errorCode, @StringRes int strId) {super("请使用资源ID的方式获取错误信息,获取String资源ID请使用getStrId()函数!");this.strId = strId;this.errorCode = errorCode;}/*** 为兼容三方框架,还是保留了String类型的参数信息*/public BaseException(int errorCode, String msg) {super(msg);this.strId = 0;this.errorCode = errorCode;}
}

然后一般展示错误信息的话是在Activity,Fragment等进行展示,可以直接使用context.getString()来获取相应的信息:

public String getMessageFromThrowable(Throwable throwable) {if (throwable instanceof BaseException) {BaseException exception = (BaseException) throwable;return getString(exception.getStrId());} else {return throwable.getMessage();}
}

还有些情况可能是在工具类中直接吐司展示错误信息的,那么建议获取顶层Activity等然后使用getString()的方式来进行处理。

3.2.4、Toast

关于Toast一般项目中都会自定义统一的Toast,单说普通情况下,如下这两种方式都会跟随你设置后的语言进行展示:

Toast.makeText(getContext().getApplicationContext(), getString(R.string.sample_text), Toast.LENGTH_SHORT).show();
Toast.makeText(getContext(), getString(R.string.sample_text), Toast.LENGTH_SHORT).show();

有的项目可能还集成了blankj作者的工具箱utilcodex,在该工具箱中有一个工具类ToastUtils,它支持使用资源ID的形式,如下:

public static void showShort(@StringRes final int resId) {show(UtilsBridge.getString(resId), Toast.LENGTH_SHORT, DEFAULT_MAKER);
}

但是使用该方式获取的始终是跟随系统的语言,如果系统语言不在App支持列表内那就会使用App默认的语言,具体原因请查看源码。

3.2.5、文字格式化

一般我们在拼接文字的时候都会用到占位符来进行处理,例如:地址是:%s?,我们把地址固定为:688 号大街(注意688后有一个空格),那么使用String.format()函数处理过后,中文情况下显示效果为:
在这里插入图片描述
然而阿拉伯语显示情况却有点异常,如下:

在这里插入图片描述

为什么688跑到后面去了,正常情况下这段文字应该从左到右显示的,然而688却显示到了右边。这是因为我们给的固定地址中包含了数字这个特殊文本(同上前文的EditText输入数字时部分手机光标的情况),系统无法确定它是属于LTR的部分还是RTL的部分,所以显示就出了问题。

那么怎么处理呢?需要使用BidiFormatter类,该类unicodeWrap()函数会检测字符串方向,并封装该字符串,官方示例如下,直接使用了BidiFormatter.getInstance()

String.format(getString(R.string.did_you_mean), BidiFormatter.getInstance().unicodeWrap(mySuggestion)
)

这种情况适合系统设置的语言为阿拉伯语的情况,如果我们是应用内切换语言,那么此时BidiFormatter.getInstance()默认的处理方式就不对了,我们需要使用其**BidiFormatter getInstance(Locale locale)**函数了,把我们本地的环境传递进去,例如:new Locale(“ar”)。这样处理完后才会正常显示,效果如下:

在这里插入图片描述

3.3、固定方向

加入有时候我们的控件不需要根据RTL布局来改变方向怎么处理呢?使用layoutDirection就可以强制该控件按照LTR或者RTL等方向来布局了。

android:layoutDirection="ltr"

参考文档

  • Android 本地化适配:RTL(right-to-left) 适配清单
  • Android阿拉伯适配rtl
  • Android官方指导
  • Material Icons Guide(不仅提供了Android的方案,还提供了iOS、Web的适配方案)
  • 支持不同的语言和文化
  • iOS官方指导

这篇关于Android 国际化与本地化探索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

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.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

vue+el国际化-东抄西鉴组合拳

vue-i18n 国际化参考 https://blog.csdn.net/zuorishu/article/details/81708585 说得比较详细。 另外做点补充,比如这里cn下的可以以项目模块加公共模块来细分。 import zhLocale from 'element-ui/lib/locale/lang/zh-CN' //引入element语言包const cn = {mess

时间服务器中,适用于国内的 NTP 服务器地址,可用于时间同步或 Android 加速 GPS 定位

NTP 是什么?   NTP 是网络时间协议(Network Time Protocol),它用来同步网络设备【如计算机、手机】的时间的协议。 NTP 实现什么目的?   目的很简单,就是为了提供准确时间。因为我们的手表、设备等,经常会时间跑着跑着就有误差,或快或慢的少几秒,时间长了甚至误差过分钟。 NTP 服务器列表 最常见、熟知的就是 www.pool.ntp.org/zo