Google Android Developer
Google Android Developer
我记得我学习Android那会儿,老师也不是很会Android,所有经常是对着Google的文档读,那个时候翻墙也是个麻烦事,再加上全英文的时候文档,看起来还是很吃力,经常是开着有道词典一句一句的翻译,等后来工作了,才意识到,这玩意是个好东西呀,但是那个时候已经不怎么去看API指南了,后来经常看一些技术书籍,我发现很多的写书人也大多数是看着官方文档的印子来写的,于是又重新打开了官网,这么一番下来,啧啧有味,你不光能看到各个版本的新技术,和需要注意的地方,还能看到很多我们不常用,却很实在的小get技术,再后来,也就是Google的中国版官网发布
- Android Developer cn
我们来看看他有什么有趣的东西吧!
一.index
他的首页,我们可以看到这么一个目录
- 首页
- Android
- Wear
- TV
- Auto
- Things
- 设计
- Material Design
- 开发
- 培训
- API指南
- 参考
- 示例
- 库
- Android Studio
- Android NDK
- Google Services
- 质量检测
- Kotlin
- 分发
- Google Play
- Play 控制台
- 最佳做法
- 营销工具
- 政策中心
- 故事
- 预览
我们作为Android开发者,其实大部分都是必须要是了解的,但是我们可以侧重的去看一些东西
- 首页
- Android
- 设计
- Material Design
- 开发
- 培训
- API指南
- 参考
- 示例
- 库
- Android Studio
- Android NDK
- 质量检测
- Kotlin
这些就是我们比较侧重的东西了,如果你是一名Android,我也希望你把这些全部去看完去熟悉,这样对你的职业生涯还是很有帮助的,我们本篇的主要内容也是介绍这些东西
二.Guide
作为第二大块,我准备说一下我们的API指南,因为这真是太赞了,我的很多的开发技巧都是上门学习到的,先来看下目录:
简介
- 应用基础知识
- 设备兼容性
- 系统权限
平台架构
- JAVA8性能
- 在ART上验证用户行为
应用组件
- Intent和Intent过滤器
- 通用Intent
- Activity
- Fragment
- 加载器
- 任务和返回栈
- 预览屏幕
- 服务
- 绑定服务
- AIDL
- 内容提供者
- 内容提供程序技术知识
- 创建内容提供程序
- 日历提供程序
- 联系人提供程序
- 存储访问程序
- 应用小组件
- 应用小部件主机
- 进程和线程
- Intent和Intent过滤器
应用资源
- 概览
- 提供资源
- 访问资源
- 处理运行时变更
- 本地化
- ICU4J Android框架API
- 语音和语音区域
- 资源类型
- 动画
- 颜色状态列表
- 可绘制对象
- 布局
- 菜单
- 字符串
- 样式
- 其他类型
应用清单
- action
- activity
- activity-alias
- application
- category
- compatible-screens
- data
- grant-uri-permission
- instrumentation
- intent-filter
- manifest
- meta-data
- path-permission
- permission
- permission-group
- permission-tree
- provider
- receiver
- service
- supports-gi-texture
- supports-screens
- uses-configuration
- uses-feature
- uses-library
- uses-permission
- uses-permission-sdk-23
- uses-sdk
用户界面
- 概览
- 布局
- 线性布局
- 相对布局
- 列表视图
- 网格视图
- 输入控件
- 按钮
- 文本字段
- 复选框
- 单选按钮
- 切换按钮
- 微调框
- 选取器
- 输出事件
- 菜单
- 设置
- 对话框
- 通知
- Toast
- 搜索
- 创建搜索界面
- 添加近期查询建议
- 添加自定义建议
- 可搜索配置
- 多窗口支持
- 拖放
- 无障碍功能
- 为应用设置无障碍功能
- 无障碍功能开发者检查单
- 否件无障碍服务
- 样式和主题
- 自定义组件
动画和图形
- 概览
- 属性动画
- 视图动画
- 可绘制动画
- OpenGL ES
- 硬件加速
计算
- 渲染脚本
- 高级渲染脚本
- RunTime API参考
- 数学类型
- 对象类型
- 转换函数
- 数学常量和函数
- 矢量数学函数
- 矩阵函数
- 四元数函数
- 原子更新函数
- 时间函数和类型
- 分配数据访问函数
- 对象特征函数
- 内核调用函数和类型
- 输入/输出函数
- 调试函数
- 图形函数和类型
- 索引
媒体和相机
- 媒体回放
- 媒体路由器
- 媒体路由提供程序
- ExoPlayer
- 支持的媒体格式
- 音频采集
- JetPlayer
- 相机
位置和传感器
- 位置和传感器
- 位置策略
- 传感器概览
- 运动传感器
- 位置传感器
- 环境传感器
连接
- 蓝牙
- BLE
- NFC
- NFC基础知识
- 高级NFC
- 基于主机的卡模拟
- WI-FI P2P
- USB
- 配件
- 主机
- SIP
- 蓝牙
文本和输入
- 复制和粘贴
- 创建IME
- 拼写检查程序
数据存储
- 存储选项
- 数据备份
- 应用安装位置
库
- 支持库
- 功能
- 设置
- 修订历史吉利
- 数据绑定库
- 测试支持库
- API参考
- 支持库
管理
- 设备政策
网络应用
- 在网络应用中支持不同屏幕
- 在WebView中构建网络应用
- 迁移到Android4.4中的WebView
- 调试网络应用
- 网络应用最佳做法
最佳实践
- 支持多种屏幕
- 分配到特定屏幕
- 屏幕兼容性模式
- 支持平板电脑和手机
- 支持多种屏幕
我们可以发现的事就是,这个目录承载着我们很多的只是点,没错,很多知识,不光是我们经常用到的,而是我们不经常用到,但是他却十分的爽歪歪的东西,我们这篇文章就是来探讨这些知识点的,不要怀疑,这件事情一定很酷。好的,那,既然如此,那我们继续来简化他吧,我们把小get点都提取出来
2.1 系统权限
应用在安装的时候,会为每个软件包提供唯一的 Linux 用户 ID,我们都只是Linux有用户组,同样的Android也有,如果我们需要管理员权限的话,在Android中的实现是在AndroidManifest.xml 的 manifest 标记中使用 sharedUserId 属性,举例:
<manifestpackage="com.liuguilin.googlesample"xmlns:android="http://schemas.android.com/apk/res/android"android:sharedUserId="android.uid.system">
2.2 Java 8
如果想使用JAVA8的一些特性,比如Lambda表达式,注解之类的,可以在Android Studio中配置Gradle
android {...defaultConfig {...jackOptions {enabled true}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}
要注意的是,目前JAVA8还不支持Instant Run
2.3 Intent
Intent十分的强大,是沟通各个组件之间的桥梁,我们可以用它做很多的事情
1.闹钟
如果我们用Intent来创建闹钟,可以这样
//创建闹钟public void createAlarm(String message, int hour, int minutes) {Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM).putExtra(AlarmClock.EXTRA_MESSAGE, message).putExtra(AlarmClock.EXTRA_HOUR, hour).putExtra(AlarmClock.EXTRA_MINUTES, minutes);if (intent.resolveActivity(getPackageManager()) != null) {startActivity(intent);}}
当然,这只是跳转到设置系统闹钟,而且我们必须加上权限
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
以及过滤器
<activity ...><intent-filter><action android:name="android.intent.action.SET_ALARM" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
</activity>
这样我们就可以实现点击设置系统闹钟了,而且这些属性,有很多,我们就不细讲了,有兴趣的就可以看下吧。
Intent地址
2.定时器
同样的,定时器也是系统的,我们可以这样做
//创建定时器public void startTimer(String message, int seconds) {Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER).putExtra(AlarmClock.EXTRA_MESSAGE, message).putExtra(AlarmClock.EXTRA_LENGTH, seconds).putExtra(AlarmClock.EXTRA_SKIP_UI, false);if (intent.resolveActivity(getPackageManager()) != null) {startActivity(intent);}}
同样的特也需要权限以及过滤器,这里注意一下过滤器只是接受到这个intent的标识
<activity ...><intent-filter><action android:name="android.intent.action.SET_TIMER" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
</activity>
3.日历
如果添加日历的事件提醒呢,说实话,这个没多少人用,因为你需要先登录Google账号,OK,我们看下代码
//创建日历事件public void addEvent(String title, String location, Calendar begin, Calendar end) {Intent intent = new Intent(Intent.ACTION_INSERT).setData(CalendarContract.Events.CONTENT_URI).putExtra(CalendarContract.Events.TITLE, title).putExtra(CalendarContract.Events.EVENT_LOCATION, location).putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin).putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end);if (intent.resolveActivity(getPackageManager()) != null) {startActivity(intent);}}
如果你也想接收这个事件的话,你也需要添加intent过滤器
<activity ...><intent-filter><action android:name="android.intent.action.INSERT" /><data android:mimeType="vnd.android.cursor.dir/event" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
</activity>
4.相机
如需打开相机应用并接收拍摄的照片或视频,请使用 ACTION_IMAGE_CAPTURE 或 ACTION_VIDEO_CAPTURE 操作。此外,还可在 EXTRA_OUTPUT extra 中指定您希望相机将照片或视频保存到的 URI 位置,所有用起来还是很方便的,我相信,相机很多人都会,但是视频,其实没有多少人会,ok,我们来看下实现,这里我就直接贴代码了
//拍照返回public void capturePhoto(String targetFilename) {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.withAppendedPath(mLocationForPhotos, targetFilename));if (intent.resolveActivity(getPackageManager()) != null) {startActivityForResult(intent, PHOTO_CODE);}}//视频返回private void dispatchTakeVideoIntent() {Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {startActivityForResult(takeVideoIntent, VIDEO_CODE);}}
这样你就可以跳转到相机了,如果想要拿到他的返回值,还得通过intent,也就是在回调里面:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {Log.i(TAG, "requestCode" + requestCode + "resultCode" + resultCode);if (resultCode == RESULT_OK) {switch (requestCode) {case PHOTO_CODE:if (data != null) {Bundle bundle = data.getExtras();Bitmap thumbnail = (Bitmap) bundle.get("data");if (thumbnail != null) {ivSrc.setImageBitmap(thumbnail);}}break;case VIDEO_CODE:if (data != null) {Uri videoUri = data.getData();mVideoView.setVideoURI(videoUri);}break;}}}
5.联系人
联系人的话还稍微复杂一点,不过这都是通用的基础语法,最多只能说是麻烦了一点,OK,我们来看下怎么跳转到联系人,然后选择联系人
//选择联系人public void selectContact() {Intent intent = new Intent(Intent.ACTION_PICK);intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);if (intent.resolveActivity(getPackageManager()) != null) {startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER);}}
这里还好,跳转到联系人,然后主要是接收到的回调,我们需要自己去查找我们需要的表单
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == RESULT_OK) {switch (requestCode) {case REQUEST_SELECT_PHONE_NUMBER:Uri contactUri = data.getData();String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};Cursor cursor = getContentResolver().query(contactUri, projection,null, null, null);if (cursor != null && cursor.moveToFirst()) {int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);String number = cursor.getString(numberIndex);Toast.makeText(this, "number:" + number, Toast.LENGTH_SHORT).show();}break;}}}
这里其实还有很多的隐藏用法,比如插入,查询联系人等等,还有发送文件,以及我们打开指定的文件类型,这些都是我们很有必要掌握的,做文件管理器的时候就要用到,只能说某个领域专注某个模块吧,但是大的方向还是要了解下
2.4 Fragment
Fragment我们这里就只说一下他的两个扩展类,DialogFragment和PreferenceFragment
1.DialogFragment
DialogFragment我一直不是很清楚他的优势在哪,但是的确看到有一些好的开源项目里面有用到,这里就说一下他的简单用法
首先是show出来,并且给上dialog的tag
public void showDialog() {mStackLevel++;android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();android.support.v4.app.Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");if (prev != null) {ft.remove(prev);}ft.addToBackStack(null);DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);newFragment.show(ft, "dialog");}
这个没什么问题,主要来看下Fragment的实现,这里代码是官网的,有一点繁琐,其实多看下家就明白了,只是一个更换主题
public class MyDialogFragment extends DialogFragment {int mNum;public static MyDialogFragment newInstance(int num) {MyDialogFragment f = new MyDialogFragment();Bundle args = new Bundle();args.putInt("num", num);f.setArguments(args);return f;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mNum = getArguments().getInt("num");int style = DialogFragment.STYLE_NORMAL, theme = 0;switch ((mNum - 1) % 6) {case 1:style = DialogFragment.STYLE_NO_TITLE;break;case 2:style = DialogFragment.STYLE_NO_FRAME;break;case 3:style = DialogFragment.STYLE_NO_INPUT;break;case 4:style = DialogFragment.STYLE_NORMAL;break;case 5:style = DialogFragment.STYLE_NORMAL;break;case 6:style = DialogFragment.STYLE_NO_TITLE;break;case 7:style = DialogFragment.STYLE_NO_FRAME;break;case 8:style = DialogFragment.STYLE_NORMAL;break;}switch ((mNum - 1) % 6) {case 4:theme = android.R.style.Theme_Holo;break;case 5:theme = android.R.style.Theme_Holo_Light_Dialog;break;case 6:theme = android.R.style.Theme_Holo_Light;break;case 7:theme = android.R.style.Theme_Holo_Light_Panel;break;case 8:theme = android.R.style.Theme_Holo_Light;break;}setStyle(style, theme);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_dialog, container, false);View tv = v.findViewById(R.id.text);((TextView) tv).setText("Dialog #" + mNum );Button button = (Button) v.findViewById(R.id.show);button.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {((DialogFragmentActivity) getActivity()).showDialog();}});return v;}
2.PreferenceFragment
PreferenceFragment是我觉得非常实用而且很棒的扩展类了,他能完美的实现设置的一些需求,我们来看下官网对他的描述
以列表形式显示 Preference 对象的层次结构,类似于 PreferenceActivity。这在为您的应用创建“设置” Activity 时很有用处
Ok,首先我们把一个fragment添加进去Activity
<fragmentandroid:name="com.liuguilin.googlesample.fragment.PrefsFragment"android:layout_width="match_parent"android:layout_height="match_parent"android:tag="pre"/>
好的,其实这个fragment特也没干什么,你需要继承的是PreferenceFragment,然后调用添加资源
addPreferencesFromResource(R.xml.preferences);
我们再res下创建xml
<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"><PreferenceCategoryandroid:title="设置"><CheckBoxPreferenceandroid:key="checkbox_preference"android:summary="这是一个不正经的勾选"android:title="勾选"/></PreferenceCategory><PreferenceCategoryandroid:title="用户"><EditTextPreferenceandroid:dialogTitle="请输入"android:key="edittext_preference"android:summary="我想知道你的性别"android:title="性别"/><ListPreferenceandroid:dialogTitle="用戶属性"android:entries="@array/entries_list_preference"android:entryValues="@array/entryvalues_list_preference"android:key="list_preference"android:summary="身份证请保密"android:title="请输入身份证"/></PreferenceCategory><PreferenceCategoryandroid:title="启动设置"><PreferenceScreenandroid:key="screen_preference"android:summary="启动预览请调整手机方向"android:title="旋转"><CheckBoxPreferenceandroid:key="next_screen_checkbox_preference"android:summary="锁定方向后不可旋转"android:title="锁定屏幕"/></PreferenceScreen><PreferenceScreenandroid:summary="官网是你的家"android:title="官网"><intentandroid:action="android.intent.action.VIEW"android:data="http://www.android.com"/></PreferenceScreen></PreferenceCategory><PreferenceCategoryandroid:title="工程模式"><CheckBoxPreferenceandroid:key="parent_checkbox_preference"android:summary="打开后你将拥有管理员权限"android:title="是否打开"/><CheckBoxPreferenceandroid:dependency="parent_checkbox_preference"android:key="child_checkbox_preference"android:layout="?android:attr/preferenceLayoutChild"android:summary="管理员权限"android:title="ROOT"/></PreferenceCategory></PreferenceScreen>
好的,运行起来是不是很酷,如果想详细的了解他的每个节点的使用,可以去看下api文档
API文档
2.5 AIDL
再来看下AIDL,一般的应用并不会使用到aidl,但是aidl确实IPC通信的一个很好的辅助手段
AIDL的话,要注意的几点就是首先要相互调用需要在同一包名,还要注意就是接口的填写,我们来看文档
官网上有一段说明:
注:只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用 AIDL。 如果您不需要执行跨越不同应用的并发 IPC,就应该通过实现一个 Binder 创建接口;或者,如果您想执行 IPC,但根本不需要处理多线程,则使用 Messenger 类来实现接口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务。
很好的诠释了AIDL,如果你不需要跨应用的话,建议使用其他的跨进程来操作
那我们如何定义呢,首先要在main目录下创建一个aidl的文件夹,然后就是三步流程
- 1.创建 .aidl 文件
此文件定义带有方法签名的编程接口。
- 2.实现接口
Android SDK 工具基于您的 .aidl 文件,使用 Java 编程语言生成一个接口。此接口具有一个名为 Stub 的内部抽象类,用于扩展 Binder 类并实现 AIDL 接口中的方法。您必须扩展 Stub 类并实现方法。
- 3.向客户端公开该接口
实现 Service 并重写 onBind() 以返回 Stub 类的实现。
当你知道这些步骤之后,我们就可以开始来编写了
package com.android.liuguilin;interface IRemoteService{int add(int a,int b);
}
这是我们定义的一个接口。我在里面只定义了一个add方法,传两个int,然后我们来看下接口服务这边的定义
public class RemoteService extends Service {@Overridepublic IBinder onBind(Intent intent) {return mBinder;}private IRemoteService.Stub mBinder = new IRemoteService.Stub() {@Overridepublic int add(int a, int b) throws RemoteException {return a + b;}};
}
ok,其实这里就是实现了一个相加的逻辑,然后把binder对象返回回去,我们最后直接bindservice就好了
private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIRemoteService = IRemoteService.Stub.asInterface(service);isBinder = true;}@Overridepublic void onServiceDisconnected(ComponentName name) {mIRemoteService = null;isBinder = false;}};
ok,拿到对象之后就可以直接去使用了,这里注意一下,如果需要跨进程,需要在清单文件中
<serviceandroid:name=".service.RemoteService"android:exported="true"/>
2.6 多窗口
android:resizeableActivity=["true" | "false"]
2.7 硬件加速
<application android:hardwareAccelerated="true" ...>
2.8 BLE
低功耗蓝牙在最近的几年应该算是很流行的了,那我们怎么去开发他呢,其实Google的文档已经详细到不能再详细了,我们一起来看下吧!
不管你是普通的蓝牙还是BLE,你都需要把权限给我加上
<uses-permission android:name="android.permission.BLUETOOTH"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
如果你想你的程序只有支持BLE的能用,那可以这样
<uses-featureandroid:name="android.hardware.bluetooth_le"android:required="true"/>
而且你在一开始,你就要判断他是否支持低功耗蓝牙
//判断是否支持BLEif (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {Toast.makeText(this, "不支持BLE设备", Toast.LENGTH_SHORT).show();//finish();}
然后我们就可以做一些初始化的操作了
//获取本地适配器BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {mBluetoothAdapter = bluetoothManager.getAdapter();}//如果没有打开,请求打开if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}
这里还得注意下,BLE是API18之后出现的,然后开始搜索
//搜索private void scanLeDevice(final boolean enable) {if (enable) {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {mScanning = false;mBluetoothAdapter.stopLeScan(mLeScanCallback);}}, 1000);mScanning = true;mBluetoothAdapter.startLeScan(mLeScanCallback);} else {mScanning = false;mBluetoothAdapter.stopLeScan(mLeScanCallback);}}//搜索回调private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {runOnUiThread(new Runnable() {@Overridepublic void run() {if(device != null){Log.i(TAG,"devices:" + device.getName());}}});}};
这样就搜索到了,如果需要通信,需要实现GATT客户端,具体的使用方法,大家可以看文档
BLE API DOC
2.9 NFC
- NFC API
2.10 WIFI-P2P
- WIFI-P2P API
2.11 USB
- USB API
2.12 复制粘贴
- 复制粘贴 API
2.13 Data Binding
- Data Binding API
2.14 WebView
- WebView
到这里大家有什么详细的就自己去细看吧!
三.Material Design
很遗憾,MD的官网需要翻墙
- Material Design
不过国内还是有中文版的
- Material Design 中文版
就是有点小尴尬
MD的设计风格一致很棒,很平滑的过渡动画,空间设计感,阴影等,不过如此,还有色彩,图片,图像等,我们把这些称为调色板,不过具体的代码实现需要看具体的面板,这份只是介绍他的一些思想,我们也不过多的去探索,毕竟在国内,还是很少有做原生风格的app的公司
四.Android Studio
AS目前来看,还真是很好用,但是如果在配置不是很强的电脑上,体验会查很多,而且还要配置好多项配置才行,还是有一定的麻烦,我个人对他的唯一不足的就是没有更多官方支持的Theme,这会让编程失去了很多的乐趣,好的,我们来看下我们这门课所学的知识
3.1 向您的项目添加 C 和 C++ 代码
官方建议我们使用2.2或者更高的版本,如果你不是很了解JNI,你可以先看一会儿JNI的文档
- JNI API
Android Studio 用于构建原生库的默认工具是 CMake,在此之前,你要先把build.properties里的这句代码删掉
android.useDeprecatedNdk = true
而使用NDK编译的话,你需要下载几个东西
- NDK
- CMake
- LLDB
其次是创建一个支持C/C++的项目,其实在我们新建工程的时候有一个选项的,就是注入C/C++的代码
大致的步骤官网也说的很详细
- 1.在向导的 Configure your new project 部分,选中 Include C++ Support 复选框。
- 2.点击 Next。
- 3.正常填写所有其他字段并完成向导接下来的几个部分。
- 4.在向导的 Customize C++ Support 部分,您可以使用下列选项自定义项目:
- C++ Standard:使用下拉列表选择您希望使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
- Exceptions Support:如果您希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
- Runtime Type Information Support:如果您希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
- 5.点击 Finish。
当然,你手动在src下创建cpp也是可以的,只不过需要设置好配置文件,我们来看下他为我们创建了什么东西,首先就是我们的c文件了
#include <jni.h>
#include <string>extern "C"
JNIEXPORT jstring JNICALL
Java_com_liuguilin_ndksample_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}
可以看到这里很简单,就定义了一个stringFromJNI方法,返回的是Hello from C++字符串,所以我们要用的话,就直接去加载他然后调用就好了
public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Example of a call to a native methodTextView tv = (TextView) findViewById(R.id.sample_text);tv.setText(stringFromJNI());}/*** A native method that is implemented by the 'native-lib' native library,* which is packaged with this application.*/public native String stringFromJNI();
}
这个时候运行后可以看到他自动为我们编译好了so,也不需要我们自己去用NDK编译了,很方便的,这就是CMake所带来的好处
我们来看下官方给我们的流程说法
- 1.Gradle 调用您的外部构建脚本 CMakeLists.txt。
- 2.CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享的对象库中,并命名为 libnative-lib.so,Gradle 随后会将其打包到 APK 中。
- 3.运行时,应用的 MainActivity 会使用 System.loadLibrary() 加载原生库。现在,应用可以使用库的原生函数 stringFromJNI()。
- 4.MainActivity.onCreate() 调用 stringFromJNI(),这将返回“Hello from C++”并使用这些文字更新 TextView。
3.2 使用 Lint 改进您的代码
在终端使用‘gradlew lint’来对项目进行检索就好了,详细的请看他的api
- Lint Api
3.3 配置方法数超过 64K 的应用
65536其实是件很烦恼的事情,这个时候虽然官方建议我们尽量优化代码,但是还是为时已晚,官方给出的解决方案
如果您的 minSdkVersion 设置为 21 或更高值,您只需在模块级 build.gradle 文件中将 multiDexEnabled 设置为 true 就好了
android {defaultConfig {...minSdkVersion 21 targetSdkVersion 25multiDexEnabled true}...
}
但是,如果您的 minSdkVersion 设置为 20 或更低值,你就需要处理了,你不光要开启multiDexEnabled,还需要添加multidex的依赖
android {defaultConfig {...minSdkVersion 15 targetSdkVersion 25multiDexEnabled true}...
}dependencies {compile 'com.android.support:multidex:1.0.1'
}
并且,如果你没有自己实现Application,那你只需要在Application里添加
<applicationandroid:name="android.support.multidex.MultiDexApplication" >...</application>
不过你都超过了65536,想必你的项目应该挺大的吧,那你应该有自己的Application,那你就需要这样去写了,先去继承MultiDexApplication
@Overrideprotected void attachBaseContext(Context base) {super.attachBaseContext(context);Multidex.install(this);}
这样就可以分包了
五.Android NDK
- NDK API
六.Kotlin
Kotlin最近虽然火了一把,官方也支持了Kotlin,但是目前来看,还是坑要多一点,而且AS要支持需要升级到3.0以及JAVA8,可以参考API
- Kotlin API
具体的用法和使用C/C++有点类似,创建项目的时候勾选Kotlin的支持
更多的语法支持,可以去Kotlin官网看看,目前个人觉得,还是把源码和View,事件处理等知识点学习好才是真理
好了,到这里就over了,可能写的不是很详细,但是也是初步的把官方文档梳理了一遍,等我下次详细的再翻阅一遍再次记述一遍,应该就很详细了,这是黄金屋,大家一定要研读!
对文章有兴趣的可以关注一下我的微信公众号或者QQ群
【刘桂林】417046685
Google Android Developer相关推荐
- 畅游Google Android Developer
初学Android那会儿,都是从csdn,开源中国,安卓巴士上查找技术资料,后面发现这些内容也都是二手的,你查找到的资料都是别人经过自己的理解再输出的,难免会有错误.很多的写书人也大多数是看着官方文档 ...
- Google Issues Cease Desist to Open Source Android Developer
Android MODer issued Cease and Desist order Last week the Android world was delivered a heavy blow. ...
- 《Google Android开发入门与实战随书视频》
1.[eoeAndroid特刊]第一期 Andriod 1.5 SDK简介 http://download.csdn.net/source/2399809 2.[eoeAndroid特刊]第二期 ...
- Google Android官方培训课程中文版
Google Android官方培训课程中文版(v0.7) Google Android团队在2012年的时候开设了Android Training板块 -http://developer.andro ...
- Google官网,Google android的产品线(important)
> Google官网,google网站重回中国(2016.12) https://developers.google.cn/ ; https://firebase.google.cn/ ; ...
- Google Android向华为“闭源”,华为手机迎来至暗时刻!
作者 | 屠敏 转载自CSDN(ID:CSDNnews) 居安思危任正非,未雨绸缪如华为.在贸易战的背景下,即使早在多年前已在多个层面做好"备胎"计划的华为,在面对美国对芯片乃至操 ...
- 《深入浅出Google Android》即将隆重上市!
<深入浅出 Google Android > 作者在线答疑活动开始啦 :http://www.hiapk.com/bbs/forum-41-1.html 随着越来越多的手机 厂商和移动运营 ...
- 在Google Android模拟器中使用SD卡(命令行和eclipse环境)
Android模拟器能够让我们使用fat32格式的磁盘镜像作为SD卡的模拟: 以下所有操作均在windows环境 首先,运行cmd,进入命令行界面(需要预先将你放置android sdk所在目录下的t ...
- Google Android开发精华教程
本文汇总整理了时下关于Google Android技术教程的下载资源,供参考. 一.入门级: <Android中文教程>中文版 [简介]:<Android中文教程>简单易懂,对 ...
最新文章
- 如流智会2021:技术结合场景 让企业知识懂员工
- 【OpenCV 4开发详解】Sobel算子
- 真·降维打击:这篇SIGGRAPH 2020论文帮你「想象」三维生物眼里的四维空间
- # Writing your-first Django-app-part 4-simple-form
- Java开发人员 2019 生态系统信息图
- DPDK 初识DPDK(十五)
- mysql5.1修改登陆密码_mysql 5.1版本修改密码及远程登录mysql数据库的方法
- (八)路径(面包屑导航)分页标签和徽章组件
- 第六十四期:微软将不再把 .NET Framework API 移植到 .NET Core 3.0
- Congestion Charging Zone 水题
- Android逆向基础笔记—Android中的常用ARM汇编指令
- 财务部门如何用OKR管理法?看最新OKR模板
- 使用js完成一个类似于小广告的功能,斜着运动,遇到边界弹回
- a non-fatal error occured whilst loading database modules
- php股票网站源代码,基于php的新三板实时股票信息接口调用代码实例
- 近视眼学计算机好吗,听说,近视的人智商更高?
- java kml_当Java遇上KML
- 学计算机得肩周炎,肩周炎的拔罐疗法
- 实现一个C语言版本的圣诞树(附源代码)
- 360 全球关键信息基础设施网络安全分析报告