精华内容
下载资源
问答
  • Android集成测试

    千次阅读 2013-09-02 13:58:01
    Android集成测试
    Android集成测试主要是在单元测试的基础上测试接口访问或者异步任务是否正确,在
    移动凤巢系统中,大概有30+个接口需要测试,他们都遵循一个特定的访问模式:前台的
    Activity获取到触发事件后,将它传给这些接口,这些接口都是AsyncTask的实现——即后台
    异步线程执行某个任务(一般是发送http请求到后端服务或者执行存取数据库等耗时操作),

    完毕后调用回调函数,示意图如下:


    一. 测试框架

     

    对于Android中这种异步接口的自动化测试需要解决3个问题:

    1) 如何获取到异步任务执行结果;
    2) 如何让上层测试代码尽量不处理任务等待;
    3) 如何处理需要登录的接口。

     

      对于问题1)每个异步任务在获取结果后就直接调用onPostExecute()方法了,测试代码
    获取不到结果,所以必须有一个专门的桩Activity负责异步任务的执行并将结果暴露出来;
    对于问题2)尽量将等待操作交给测试基类,上层测试代码只需要执行被测逻辑;对于问题
    3)采用模板模式,如果接口需要登录则先执行登录操作后再调用,整体解决方案如下:


    其中桩Activity的逻辑如下,它实际决定接口的调用方式,如果被测接口需要登录则先
    登录后调用,如果不需要登录则直接调用。



     可以看到isCompleted是标识异步任务是否执行完毕的,无论异步任务返回是onSuccess、
    onError还是onIOException都会进行置位;result则是异步调用的返回,可以看到这里无论
    接口调用是成功、失败还是io异常都会将这个结果暴露出来以使测试代码能够获取到;
    interfaceAction是测试代码需要实现的接口,内容如下:


    由于有些接口是必须登录才能访问的,所以前两个接口实现是为其服务的,如果访问的
    接口必须处于登录状态则先调用login()方法,然后再调用实际的action()方法。另外,书写
    测试代码的时候为了减少对异步任务等待的代码以及显示对InterfaceActivity这个桩Activity


    的调用还需要完善测试基类:
    这样上层test case只需要关心具体的测试逻辑而不用关心异步调用及等待处理。
     
    二. 测试方法
     
      以商桥访问接口测试为例,由于它是一个需要登陆才能访问的接口,写自动化case的
    时候需要完成两个类:BridgeAction和BridgeTest。其中BridgeAction主要是接口的调用,
    BridgeTest是测试内容:


    这里BaseLoginAction实现了needLogin()和login()方法,主要是登录逻辑,BridgeAction
    的action()是真正接口的调用。


    测试类主要是对BridgeAction的调用,它可以向接口传递不同的参数,同时也可传递登
    录操作的用户名和密码。waitAsyncTaskComplete(action)完成了接口逻辑的调用及时间的等待,
    测试代码只需着重关注result并进行断言。
     
    三. 总结
     
      异步接口的集成测试的侧重点在于Android手机端向服务器端发送的请求是否正确,以
    上测试CASE的断言与后端数据其实是强耦合的,即后端caiye这个账户的数据变化可能导致
    CASE的fail,所以可以考虑引入hamcrest包,做一些匹配校验,主要测试正常和异常情况服
    务器返回的内容是否符合预期,比如上面最后一个断言可以写成:assertEquals(intValue(),
    greaterThan(0));当然,服务器端接口的正确性正常情况下应该由服务器端的自动化Case来保
    证,这样才不至于前后端测试紧耦合在一起。

    Android集成测试主要是在单元测试的基础上测试接口访问或者异步任务是否正确,在
    移动凤巢系统中,大概有30+个接口需要测试,他们都遵循一个特定的访问模式:前台的
    Activity获取到触发事件后,将它传给这些接口,这些接口都是AsyncTask的实现——即后台
    异步线程执行某个任务(一般是发送http请求到后端服务或者执行存取数据库等耗时操作),
    完毕后调用回调函数,示意图如下:


    一. 测试框架

     

    对于Android中这种异步接口的自动化测试需要解决3个问题:

    1) 如何获取到异步任务执行结果;
    2) 如何让上层测试代码尽量不处理任务等待;
    3) 如何处理需要登录的接口。

     

      对于问题1)每个异步任务在获取结果后就直接调用onPostExecute()方法了,测试代码
    获取不到结果,所以必须有一个专门的桩Activity负责异步任务的执行并将结果暴露出来;
    对于问题2)尽量将等待操作交给测试基类,上层测试代码只需要执行被测逻辑;对于问题
    3)采用模板模式,如果接口需要登录则先执行登录操作后再调用,整体解决方案如下:


    其中桩Activity的逻辑如下,它实际决定接口的调用方式,如果被测接口需要登录则先
    登录后调用,如果不需要登录则直接调用。



    可以看到isCompleted是标识异步任务是否执行完毕的,无论异步任务返回是onSuccess、
    onError还是onIOException都会进行置位;result则是异步调用的返回,可以看到这里无论
    接口调用是成功、失败还是io异常都会将这个结果暴露出来以使测试代码能够获取到;
    interfaceAction是测试代码需要实现的接口,内容如下:


    由于有些接口是必须登录才能访问的,所以前两个接口实现是为其服务的,如果访问的
    接口必须处于登录状态则先调用login()方法,然后再调用实际的action()方法。另外,书写
    测试代码的时候为了减少对异步任务等待的代码以及显示对InterfaceActivity这个桩Activity


    的调用还需要完善测试基类:
    这样上层test case只需要关心具体的测试逻辑而不用关心异步调用及等待处理。
     
    二. 测试方法
     
      以商桥访问接口测试为例,由于它是一个需要登陆才能访问的接口,写自动化case的
    时候需要完成两个类:BridgeAction和BridgeTest。其中BridgeAction主要是接口的调用,
    BridgeTest是测试内容:


    这里BaseLoginAction实现了needLogin()和login()方法,主要是登录逻辑,BridgeAction
    的action()是真正接口的调用。


    测试类主要是对BridgeAction的调用,它可以向接口传递不同的参数,同时也可传递登
    录操作的用户名和密码。waitAsyncTaskComplete(action)完成了接口逻辑的调用及时间的等待,
    测试代码只需着重关注result并进行断言。
     
    三. 总结
     
      异步接口的集成测试的侧重点在于Android手机端向服务器端发送的请求是否正确,以
    上测试CASE的断言与后端数据其实是强耦合的,即后端caiye这个账户的数据变化可能导致

    展开全文
  • Android 集成谷歌地图

    万次阅读 热门讨论 2018-08-22 14:17:41
    1、Android集成谷歌地图 项目需求,地图展示,设备点聚合,设备站点,设备过滤等功能。我只针对我涉及到的技术做一下总结,希望能帮到开始接触谷歌地图的伙伴们。 1、集成步骤: ①在项目的modle的build.gradle中...

    1、Android集成谷歌地图

    项目需求,地图展示,设备点聚合,设备站点,设备过滤等功能。我只针对我涉及到的技术做一下总结,希望能帮到开始接触谷歌地图的伙伴们。

    1、集成步骤:

    ①在项目的modle的build.gradle中添加依赖如下:

    implementation 'com.google.android.gms:play-services-maps:12.0.1'
    
    //    地图操作工具类,添加标记等
    compile 'com.google.maps.android:android-maps-utils:0.5+'

     2、集成完了后,需要展示地图,这里由于谷歌地图是已经被屏蔽,需要翻墙操作才能展示,项目操作步骤如下:

    ①首先我们要注册一个谷歌账号

    ②使用谷歌账号登录谷歌地图开发者平台(登录网站:https://cloud.google.com/maps-platform/?hl=zh-CN),点击控制台,如图

    点击控制进入控制台进行如下操作,生成谷歌地图的appkey:

    点击API秘钥,生成秘钥,在生成的秘钥界面上我们点击秘钥限制,设置成android ,点击确定就生成了我们所需的appkey。

    3、项目需求

    1、地图展示

    1.地图展示:分为两加载地图,一种是在activity中动态或者是静态加载我们的谷歌地图的fragment,进行显示。首先说一下在activity中静态加载地图的fragment。核心代码如下:

    ①布局:

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.mapwithmarker.MapsMarkerActivity" />

    ②代码中:

      SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    

    这样一张谷歌地图就展示出来,显示的原因是通过mapFragment.getMapAsync()方法映射注册回调地图监听(因为谷歌地图被屏蔽了,所以需要翻墙才能看到地图,如果没有翻墙,是空白一片,并且android手机里面必须安装谷歌三件套,否则也不能显示)。

    ③显示谷歌地图的activity要实现onMapReadyCallBack接口,重写onMapReady(GoogleMap googleMap)方法,在这个方法中我们进行逻辑操作,比如是添加mark点,mark点聚合等。

    2、在fragment显示谷歌地图(与activity比较有一些不同点)

    ①布局中的代码:

     <com.google.android.gms.maps.MapView
            android:layout_marginTop="1dp"
            android:id="@+id/mapview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    

    ②在代码中code如下:

       mMap = (MapView) mView.findViewById(R.id.mapview);
            mMap.onCreate(savedInstanceState);
            mMap.onResume();
    
            try {
                MapsInitializer.initialize(getActivity());
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            int errorCode = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(this.getActivity());
    
            if (ConnectionResult.SUCCESS != errorCode) {
                GooglePlayServicesUtil.getErrorDialog(errorCode,
                        this.getActivity(), 0).show();
            } else {
                mMap.getMapAsync(this);
            }

    ③其他的步骤和activity相同。需要fragment 实现onMapReadyCallBack接口,重写onMapReady(GoogleMap googleMap)方法,在此方法中进行逻辑操作。

    2、在地图上添加mark点

    在onMapReady(GoogleMap googleMap)方法中,调用返回的googleMap实例添加mark点。核心代码是

     googleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker").icon(descriptor));

    注释:position:就是mark点的经纬度,title:mark的标题,icon :是mark的背景图片。

    下面代码是实现自定义 mark背景图片及颜色设置,文字设置的相应方法,抽离于源码,想详细了解可以查看源码:

      /**
         * 设置站点包含设备数量
         *
         * @param context
         * @return
         */
        private SquareTextView makeSquareTextView(Context context) {
            SquareTextView squareTextView = new SquareTextView(context);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(-2, -2);
            squareTextView.setLayoutParams(layoutParams);
            squareTextView.setId(amu_text);
            int twelveDpi = (int) (12.0F * this.mDensity);
            squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi);
            return squareTextView;
        }
    
        /**
         * 设置站点图片背景色
         *
         * @return
         */
        private LayerDrawable makeClusterBackground() {
            this.mShapeDrawable = new ShapeDrawable(new RectShape());
    
            ShapeDrawable outline = new ShapeDrawable(new RectShape());
            outline.getPaint().setColor(-2130706433);
            LayerDrawable background = new LayerDrawable(new Drawable[]{outline, this.mShapeDrawable});
            int strokeWidth = (int) (this.mDensity * 3.0F);
            background.setLayerInset(1, strokeWidth, strokeWidth, strokeWidth, strokeWidth);
            return background;
        }
    
        /**
         * 获得站点图标需要显示的数字的格式 小于10的后面没有添加+,反之则添加
         *
         * @param bucket
         * @return
         */
        protected String getClusterText(int bucket) {
            return bucket < 9 ? String.valueOf(bucket) : bucket + "+";
        }
    
        /**
         * 给画笔设置颜色,目的是画mark点圆图片的颜色。
         *
         * @param clusterSize
         * @return
         */
        public int getColors(int clusterSize) {
            float hueRange = 220.0F;
            float sizeRange = 300.0F;
            float size = Math.min((float) clusterSize, 300.0F);
            float hue = (300.0F - size) * (300.0F - size) / 90000.0F * 220.0F;
            return Color.HSVToColor(new float[]{hue, 1.0F, 0.6F});
        }
    

    上述就完成了地图添加mark点,并且可以自定义mark点样式。

    3、mark点点聚合

    实现点聚合需要借助两个核心类,ClusterItem(聚合条目),ClusterMananger(聚合管理类)

    实现步骤是:自己定义一个java类继承ClusterItem,每个人的项目中的mark点信息有可能不同,自己在此java类中定义属性。

    使用此java类封装每个mark定数据,并调用ClusterMananger中的addItem(mark)方法,把数据交给ClusterMananager处理,这是使用google地图默认的聚合渲染模式,如果需要定制,需要创建一个java类继承CluseterMananger,进行相应的定制。

    代码如下:

     if (mClusterManager == null) {
                mClusterManager = new ClusterManager<MarkItem>(getApplication(), googleMap);
            }
            googleMap.setOnCameraIdleListener(mClusterManager);
            googleMap.setOnMarkerClickListener(mClusterManager);
            mClusterManager.setOnClusterItemClickListener(this);
            mClusterManager.setOnClusterClickListener(this);
            addItems();
    ........................................................................................
    
        /**
         * 整合mark点数据
         */
        private void addItems() {
            double lat = 51.5145160;
            double lng = -0.1270060;
    
            String title = "This is a mark";
            String snippet = "every mark distriub";
    
            for (int i = 0; i < 10; i++) {
                double offset = i / 360d;
                lat = lat + offset;
                lng = lng + offset;
                MarkItem offsetItem = new MarkItem(lat, lng, title, snippet);
                mClusterManager.addItem(offsetItem);
            }
        }
    这样就完成了基本的点聚合。
    

    谢谢浏览

    展开全文
  • Android 集成 FFmpeg (一) 基础知识及简单调用

    万次阅读 多人点赞 2017-08-12 23:28:19
    本系列第二篇:Android 集成 FFmpeg (二) 以命令方式调用 FFmpeg 前言 网上关于 Android 集成 FFmpeg 的文章很多,但大多数都只介绍了步骤,没有说明背后的原理,若之前没有集成底层库的经验,那就会“神知无知...

    本系列第二篇:Android 集成 FFmpeg (二) 以命令方式调用 FFmpeg

    前言

    网上关于 Android 集成 FFmpeg 的文章很多,但大多数都只介绍了步骤,没有说明背后的原理,若之前没有集成底层库的经验,那就会“神知无知”的走一步看一步,出错几率很大,出错了也不知道原因,然后会乱猜“这篇教程有问题“,“换个版本估计可以”,甚至“电脑有问题,重装下系统试试”。

    为什么会出现这种情况,答案很简单:欲速则不达,要实现 Android 端集成 FFmpeg 功能,那就要掌握必需的基础知识,如果连 JNI、NDK都不了解,一上来就参考几秒钟搜出来的集成步骤开始集成,那只会被各种莫名其妙的异常完虐,如果运气好很快就实现了功能呢? 在我看来这是更大的损失,这些你没有掌握的知识如此接近却又悄悄溜走。

    那么在 Android 端集成 FFmpeg 需要掌握哪些基础知识呢?个人认为以下内容是需要了解的:

    1. JNI
    2. CPU架构
    3. 交叉编译
    4. NDK
    5. FFmpeg 简介

    以下知识点阐述是经过反复推敲的,不是随意复制而来,其中融入自己的理解,以个人易于理解的方式记录下来,希望能给你带来帮助。

    1.JNI

    JNI,即 Java Native Interface ,是 Java 提供用来与其他语言通信的 api ,“其他语言”意味不止局限于 C 或 C++ ,也可以调用除 C 和 C++ 之外的语言,只是大多数情况下调用 C 或 C++ ; “通信”意味着 Java 和 其他语言之间可以相互调用,不止局限于 Java 调用其他语言,其他语言也可以主动调用 Java .

    Java 虚拟机实现了跨平台特性, 无法很好的实现与操作系统相关的本地操作,而 C 或 C++ 可以,同时代表着 C 或 C++ 不具备 Java 的跨平台能力,那么当我们在程序中使用 JNI 功能时,就必须关注程序的平台可移植性, JNI 标准要求本地代码至少能工作在任何Java 虚拟机环境。

    简而言之,跨平台的 Java 调用了不跨平台的 C/C++,使程序丧失了跨平台性,这就是 JNI 的副作用,所以可以不使用 JNI 时就尽量避免。而大多数不可避免的情况是:已存在用 C/C++ 写的程序/库或者 Java 语言不支持程序所要实现的特性,比如 ffmpeg 是由 C 编写的,则必须要通过 JNI 实现调用。

    JNI 的实现步骤很简单,如下:

    1. 编写带有 native 方法的 Java 类
    2. 生成该类扩展名为 .h 的头文件
    3. 创建该头文件的 C/C++ 文件,实现 native 方法
    4. 将该 C/C++ 文件编译成动态链接库
    5. 在Java 程序中加载该动态链接库

    动态链接库是一组源代码的模块,其中包含可供应用程序调用的函数。比如 Windows 下的 .dll 文件就是一种动态链接库,也就是说 Java 程序在 Windows 中运行,所需的动态链接库就是 .dll 文件; 如果 Java 程序在 Linux 中运行,所需的动态链接库就是 .so 文件 ,这里 JNI 的副作用已初见端倪,本来无视操作系统的 Java ,因为 JNI ,就要考虑运行环境是 Windows 还是 Linux 。除此之外,还要考虑 CPU 架构,这也是 Android 中使用 JNI 主要需考虑的 so 库兼容型问题。

    对于 Java 程序来说,需要的仅仅是编译后的动态链接库,不需要 C/C++ 文件和 .h 头文件。Android 亦如此,网上很多 Android NDK 教程会把需要编译的 C/C++ 源码放入 Android 工程中,形成类似这样的工程结构:

    这里写图片描述

    这对新手来说可能会产生误导,误以为 Android 工程需要 C/C++ 文件或 .h 头文件或者其他的文件,要清楚的是, Android 工程需要的仅仅是编译后的 .so 库,所以我们可以在工程之外编译完后,只将 .so 库移植到工程中。那为什么大多数教程会把源码先移植到 Android 工程中再去编译呢?目的只有一个:节省目录的切换以及 .so 库的复制时间,实际上这些时间微乎其微,我推荐新手将编译操作于工程外进行,更易理解。

    2.CPU 架构

    我们都知道 CPU 是什么,那 CPU 架构到底是什么呢?回归到“架构”这个词本身含义,CPU 架构就是 CPU 的框架结构、设计方案,处理器厂商以某种架构为基础,生产自己的 CPU,就好比“总-分-总”是文章的一种架构,多篇文章可以都基于“总-分-总”架构。

    常见的 CPU 架构有 x86、x86-64 以及 arm 等, x86-64 其实也是基于 x86 架构,只是在 x86 的基础上做了一些扩展,以支持 64 位程序的应用,常见的 Intel 、AMD 处理器都是基于 x86 架构的。

    而 x86 架构主打的是 pc 端,对于移动端,arm 架构处于霸主地位 ,由于其体积小、低功耗、低成本、高性能的优点,被广泛应用在嵌入式系统中,目前大多数安卓、苹果手机的 CPU 都基于 arm 架构,此处所说的 arm 架构指 arm 系列架构,其中包括 ARMv5 、ARMv7 等等。

    最后再看 Android 端 , Android 系统目前支持 ARMv5、ARMv7、ARMv8、 x86 、x86_64、MIPS 以及 MIPS64 共七种 CPU 架构,也就是说除此之外其他 CPU 架构的硬件并不能运行 Android 系统。

    3.交叉编译

    在某个平台上,编译该平台的可执行程序,叫做本地编译,比如在 Windows 平台上编译 Windows 自身的可执行程序;在 x86 平台上,编译 x86 平台自身的可执行程序。

    在某个平台上,编译另一种平台的可执行程序,就是交叉编译,比如在 x86 平台上,编译 arm 平台的可执行程序,这也是 Android 端使用最多的交叉编译类型。

    在交叉编译时,由于主机与目标的体系架构、环境不同,所以交叉编译比本地编译复杂很多,需要一些工具来解决主机与目标不同特性的问题,这些工具构成的工具集就叫做交叉编译链。

    既然交叉编译比本地复杂很多,那为什么不使用本地编译,比如在 arm 平台编译 arm 平台的可执行程序呢?这是因为目标平台存储空间和计算能力通常是有限的,而编译过程需要较大的存储空间和较快的计算能力,但目标平台无法提供。

    4.NDK

    我们需要的是 arm 平台的动态库,而这一编译过程往往是在 x86 平台上进行,所以属于交叉编译,需要交叉编译链来实现,所以 NDK(Native Development Kit )中提供了交叉编译链,方便开发。

    Android 中包括七种 CPU 架构,NDK 中自然就有与之对应的交叉编译链,以下是 Android 官网对此的表格描述:

    | 架构 | 工具链名称 |
    |: ------ 😐:-----------😐
    | 基于 ARM | arm-linux-androideabi- < gcc-version > |
    | 基于 ARM64 | aarch64-linux-android- < gcc-version > |
    | 基于 x86 | x86- < gcc-version > |
    | 基于 X86-64 | x86_64- < gcc-version > |
    | 基于 MIPS | mipsel-linux-android- < gcc-version > |
    | 基于 MIPS64 | mips64el-linux-android-- < gcc-version >
    |

    除此之外,NDK 还提供了一些原生标头和共享库文件,包括 C/C++ 支持库、从 C/C++ 代码中可以向 Android 系统输出日志的 < android/log.h > 等等,可以点击这里了解更多,总之,NDK 是用来帮助我们实现交叉编译的工具。

    在实际使用时,比较重要的是 Android.mk 语法,内容并不多,但你必须了解,不然只复制别人的配置很容易出错,关键是你无法真正的掌握这部分知识,而最好的学习方法就是仔细阅读几遍 Android.mk 官网教程

    另外还需要了解什么是 ABI ,ABI 即 application binary interface ,应用程序二进制接口,顾名思义,“二进制接口”说明这是程序与系统之间的底层接口,它定义了程序如何与系统交互。我们应该指定每个 CPU 架构所对应的 ABI,所以 Android 中就出现了 armeabi 、armeabi-v7a、arm64-v8a、x86、x86_64、mips 以及 mips64 目录来区分不同的 ABI ,我们将编译好的动态库放入对应 CPU 架构的 ABI 目录中就可以了。

    掌握了以上知识点,才能知道 Android 集成 FFmpeg本质上是在做什么,为什么要这样做。不只是集成 FFmpeg,这些知识对于任何底层库的集成都是通用、必要的。

    1. FFmpeg 简介
      ===

    FFmpeg 是一套可以用来记录、转换数字音频视频,并能将其转化为流的开源计算机程序

    FFmpeg 被很多开源项目和软件使用,比如暴风影音、QQ影音、格式工厂等,另外在我常用的 App 中也发现了它的身影:

    这里写图片描述

    其实写到这里,有点犹豫非操作步骤的内容是否叙述过多了,后来想想,这正是这篇文章的初衷,尽量全面清楚,透过表面操作看本质,另外最重要的一个目标,就是争取做到授人以渔,我相信这也是大家对所有技术教程文章的一个美好愿景。

    下面分为 3 个部分介绍 FFmpeg的编译及 Android 端的简单调用:

    1. 准备

    2. 编译 FFmpeg

    3. 编译动态库及调用

    4. 准备
      ===

    • Linux 环境(Ubuntu 16.04):从个人经验而谈,准备 Linux 环境比 Windows 环境编译的工作量小。
    • 下载NDK(android-ndk-r14b) :网上有些教程美言曰“NDK向后兼容”,其实查阅 NDK 版本更新说明就能解决。
    • 下载 FFmpeg (ffmpeg-3.3.3): 官网下载链接:https://ffmpeg.org/download.html
    1. 编译 FFmpeg
      ===
      编译环境为 x86 的 Linux ,运行环境为 arm 架构的 Android 系统,目标是把 FFmpeg 源码编译成 Android 端可调用的动态库,这属于交叉编译,所以需要 NDK 提供的交叉编译工具,这是这一步骤的本质意义。

    Android 工程中只支持导入 .so 结尾的动态库,形如:libavcodec-57.so 。但是FFmpeg 编译生成的动态库默认格式为 xx.so.版本号 ,形如:libavcodec.so.57 , 所以需要修改 FFmpeg 根目录下的 configure 文件,使其生成以 .so 结尾格式的动态库:

    # 将 configure 文件中的:
    SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' 
    LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"' 
    SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' 
    SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
    
    #替换为:
    SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
    LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
    SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
    SLIB_INSTALL_LINKS='$(SLIBNAME)'
    
    

    在编译 FFmpeg 之前,我们需要修改 FFmpeg 的编译选项,主要目的如下:

    • 规定编译方式,使其通过交叉编译生成我们需要的动态库。
    • 选择所需功能,针对需求定制 FFmpeg 功能,精简动态库。

    比如我们需要对 mp3 文件进行剪切、合并等操作,则应开启 mp3 格式编码与解码功能( FFmpeg 本身不支持 mp3 格式编码,需要引入 libmp3lame 库)。

    怎么修改 FFmpeg 的编译选项呢?在 FFmpeg 根目录下通过 ./configure 命令进行设置,但是为了方便记录与修改,我们选择在根目录下建立一个脚本文件来运行 ./configure 命令。

    针对所需功能,脚本文件如下 :

    #!/bin/bash  
    NDK=/home/yhao/Android/android-ndk-r14b
    SYSROOT=$NDK/platforms/android-14/arch-arm/
    TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
    
    CPU=arm
    PREFIX=$(pwd)/Android/$CPU
    MP3LAME=/home/yhao/sf/lame-3.99.5/android
    
    ./configure \
        --prefix=$PREFIX \          #规定编译文件在哪里生成
        --enable-cross-compile \    #启用交叉编译方式
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \  #交叉编译链
        --target-os=linux \         #目标系统
        --arch=arm \                #目标平台架构
        --sysroot=$SYSROOT \        #交叉编译环境
        --extra-cflags="-I${MP3LAME}/include" \                 #额外需要的头文件
        --extra-ldflags="-L${MP3LAME}/lib" \                    #额外需要的库                 
        --enable-shared \           #生成动态库(共享库)
        --disable-static \          #禁止生成静态库
        --disable-doc \             #禁用不需要的功能,下同
        --disable-ffserver \
        --disable-parsers \
        --disable-protocols \
        --disable-indevs \
        --disable-bsfs \
        --disable-muxers \
        --disable-demuxers \
        --disable-hwaccels \
        --disable-decoders \
        --disable-encoders \
        --enable-parser=mpegaudio \ #启用需要的功能,下同
        --enable-protocol=http \
        --enable-protocol=file \
        --enable-libmp3lame \
        --enable-encoder=libmp3lame \
        --enable-encoder=png \
        --enable-demuxer=mp3 \
        --enable-muxer=mp3 \
        --enable-decoder=mjpeg \
        --enable-decoder=mp3
    

    除强迫症风格的注释之外,再对个别配置进行说明:

    • –sysroot=$SYSROOT : 前言中提到 NDK 除了提供 交叉编译链 以外,还提供一些原生标头和共享库文件,通过此配置指定了交叉编译环境,使其在编译过程中能够引用到 NDK 提供的原生标头和共享库文件,其中 android-14 目录指定了生成动态库最低支持的 Android 版本,嗯~ ,这里可以说它是向后兼容的。

    • –target-os=linux :Android 内核为 Linux ,故在此指定为 linux ,如果要编译的目标系统为 ios ,则指定为 darwin 。

    • –cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- : 类似于通配符方式指定 bin 目录下以 arm-linux-androideabi-
      开头的交叉编译工具,假如不支持这种配置方式则需分别指定,比如在交叉编译 libmp3lame 时就是分别指定的:

    这里写图片描述

    • –extra-cflags 和 --extra-ldflags : 由于开启 mp3 编码需要引入 libmp3lame 库,所以需要指定编译好的 libmp3lame 头文件和库文件的路径,这样在编译时才能正确引用到 libmp3lame 。这里是我编译好的 libmp3lame 库,下载后指定对应路径即可 。

    • FFmpeg 功能的开启和禁用 : 在 FFmpeg 源码根目录下通过 ./configure --help 命令查看所有配置选项,针对需求配置,这里针对 mp3 文件操作的功能进行配置,禁用了很多不需要的功能,大幅精简动态库,从而减小 APK 大小。

    接下来运行该脚本文件使配置生效,比如我的脚本文件名为 config.sh :

    sh config.sh
    

    运行成功后会输出生效的配置,可以看到此时支持的编解码:

    这里写图片描述

    ok ,现在已经配置完编译选项了,接下来就可以开始编译了啦~

    sudo make -j4
    

    编译完成不要忘记安装:

    sudo make install
    

    然后就可以看到成功生成:

    这里写图片描述

    1. 编译动态库及调用
      ====
      你可能会疑问,上一步已经编译 FFmpeg 源码生成动态库了,为什么这一步还是“编译动态库”呢?其实这个问题等效于:上一步中生成的动态库可以直接在 Android 工程中使用吗?

    答案是否定的,回到文章开头 JNI 的使用步骤,在编写带有 native 方法的 Java 类后,紧接着就是用 C/C++ 实现本地接口,这是 Java 与 C/C++ 交互的必要通道。

    所以接下来需要编写本地接口,在本地接口中调用上一步编译好的 FFmpeg 动态库,然后将本地接口也编译成动态库,供 Android 调用,这一步还需要“编译动态库”。

    网上有些教程在这一步把 FFmpeg 源码、动态库全部复制到 Android 工程中,然后在工程中新建本地接口、mk文件… 花里胡哨的看的我头皮发麻~ 这一步我推荐在 Android 工程之外进行,直到生成最终可用的动态库之后,再拷贝到 Android 工程中直接使用。

    首先新建一个文件夹,取名随意,比如 “ndkBuild ”,这个目录就作为我们的工作空间,然后在 ndkBuild 下新建 jni 文件夹, 作为编译工作目录。 OK~ 接下来按照前言中的 jni 步骤来划分操作:

    1. 编写带有 native 方法的 Java 类

    package com.jni;
    
    public class FFmpeg {
        
        public static native void run();
    
    }
    
    

    2. 生成该类扩展名为 .h 的头文件

    在 Android Studio 的 Terminal 中 切换到 java 目录下,运行 javah 命令生成头文件:

    javah -classpath .  com.jni.FFmpeg
    

    网上很多教程需要先生成 .class 文件,而我在 java 1.8 环境下亲测以上一句命令即可。

    3. 创建该头文件的 C/C++ 文件,实现 native 方法

    将生成的 com_jni_FFmpeg.h 文件剪切到 ndkBuild 的 jni 目录下,创建对应的 C 文件 com_jni_FFmpeg.c :

    #include <android/log.h>
    #include "com_jni_FFmpeg.h"
    
    #include <stdlib.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavfilter/avfilter.h"
    
    JNIEXPORT void JNICALL Java_com_jni_FFmpeg_run(JNIEnv *env, jclass obj) {
      
        char info[40000] = {0};
        av_register_all();
        AVCodec *c_temp = av_codec_next(NULL);
        while(c_temp != NULL){
           if(c_temp->decode!=NULL){
              sprintf(info,"%s[Dec]",info);
           }else{
              sprintf(info,"%s[Enc]",info);
           }
           switch(c_temp->type){
            case AVMEDIA_TYPE_VIDEO:
              sprintf(info,"%s[Video]",info);
              break;
            case AVMEDIA_TYPE_AUDIO:
              sprintf(info,"%s[Audio]",info);
              break;
            default:
              sprintf(info,"%s[Other]",info);
              break;
           }
           sprintf(info,"%s[%10s]\n",info,c_temp->name);
           c_temp=c_temp->next;
        }
    __android_log_print(ANDROID_LOG_INFO,"myTag","info:\n%s",info);
    }
    

    这段程序用于输出 FFmpeg 支持的编解码信息,通过 < android/log.h > 的 __android_log_print 方法可以直接将信息输出到 Android Studio 的 logcat 。

    4. 将该 C/C++ 文件编译成动态链接库

    编译 FFmpeg 源码时的实际入口是通过 FFmpeg 提供的 makefile ,而在这一步,将直接使用 NDK 提供的编译方法,需要提供 Application.mk 和 Android.mk 文件。

    首先在 jni 目录下创建 Application.mk 文件 :

    APP_ABI := armeabi
    APP_PLATFORM=android-14
    

    APP_ABI 表示编译生成 armeabi 架构的 so 库,APP_PLATFORM 表示最低支持的 Android 版本。

    然后在 jni 目录下创建 Android.mk 文件:

    LOCAL_PATH:= $(call my-dir)
    
    INCLUDE_PATH:=/home/yhao/sf/ffmpeg-3.3.3/Android/arm/include
    FFMPEG_LIB_PATH:=/home/yhao/sf/ffmpeg-3.3.3/Android/arm/lib
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavcodec
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavcodec-57.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
     
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavformat
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavformat-57.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
     
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libswscale
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libswscale-4.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
     
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavutil
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavutil-55.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
     
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavfilter
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavfilter-6.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
     
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libswresample
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libswresample-2.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libpostproc
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libpostproc-54.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavdevice
    LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavdevice-57.so
    LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := ffmpeg
    LOCAL_SRC_FILES := com_jni_FFmpeg.c 
    LOCAL_C_INCLUDES := /home/yhao/sf/ffmpeg-3.3.3
    LOCAL_LDLIBS := -lm -llog
    LOCAL_SHARED_LIBRARIES := libavcodec libavfilter libavformat libavutil libswresample libswscale libavdevice
    include $(BUILD_SHARED_LIBRARY)
    

    对于 Android.mk 文件前面提到过,最好的学习方法就是仔细阅读几遍 Android.mk 官网教程 。 简要说明一下,此文件将之前编译好的 FFmepg 动态库通过 NDK 提供的预编译方式编译,通过 prebuilt 这个单词也能猜到它的含义,点击了解 NDK 预编译, 最后将 com_jni_FFmpeg.c 编译成名为 ffmpeg 的动态库。

    此时 jni 目录下应有以下四个文件:

    这里写图片描述

    请无视 Android.mk 文件上的小锁儿~ 。然后在 jni 目录下运行 (注意要把 ndk 添加到环境变量) :

    ndk-build
    

    大功告成 ,此时在 ndkBuild 目录下生成了 libs 和 obj 目录,而 Android 需要的最终的动态库就在 libs 目录下:

    5. 在Java 程序中加载该动态链接库

    将 libs 目录下的 armeabi 文件夹整体拷贝到 Android Studio 工程的 libs 文件夹下,当然如果你的工程已经存在 armeabi 目录,就把该目录下的动态库拷贝到工程的 armeabi 目录下。

    在 FFmpeg 中加载动态库:

    package com.jni;
    
    
    public class FFmpeg {
    
        static {
            System.loadLibrary("avutil-55");
            System.loadLibrary("avcodec-57");
            System.loadLibrary("avformat-57");
            System.loadLibrary("avdevice-57");
            System.loadLibrary("swresample-2");
            System.loadLibrary("swscale-4");
            System.loadLibrary("postproc-54");
            System.loadLibrary("avfilter-6");
            System.loadLibrary("ffmpeg");
        }
    
        public static native void run();
    }
    
    

    记得在应用的 build.gradle 文件中 android 节点下添加动态库加载路径:

        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }
    

    然后在程序中调用 FFmpeg.run() 方法 ,可以看到 logcat 输出了 FFmpeg 的编解码信息:

    这里写图片描述

    总结

    这篇文章较多篇幅介绍了 JNI 相关的基础知识,对 JNI 经验缺乏的人应该会有较多帮助,尤其是交叉编译和 CPU 架构部分,如果一个月前的我看到估计都感激涕零了,当初一脸茫然的按照网上的教程集成,殊不知不了解这些知识是真的愣头青。

    此文中仅仅实现了 Android 端获取 FFmpeg 编解码信息,而要实际使用的话,就要掌握 FFmpeg 提供的函数或者通过命令方式调用,后者难度较小,另外还有 libmp3lame 库的编译,下篇文章一起总结。

    关注公众号,Get 更多知识点

    展开全文
  • Android 集成支付宝支付

    千次阅读 2017-11-23 11:05:04
    Android 集成支付宝支付1.首先集成支付宝SDK官方文档dizhi :https://docs.open.alipay.com/204/105296/SDK的下载下载地址:https://doc.open.alipay.com/doc2/detail.htm?treeId=54&articleId=104509&docType=1下载...

    Android 集成支付宝支付

    1.首先集成支付宝SDK

    官方文档地址 :https://docs.open.alipay.com/204/105296/

    SDK的下载下载地址:https://doc.open.alipay.com/doc2/detail.htm?treeId=54&articleId=104509&docType=1

    这里写图片描述

    下载完成后 把压缩包解压,然后找到这个.jar文件,将他导入你的项目中。
    这里写图片描述
    或者在app module下的build.gradle下手动添加依赖,如下代码所示:

    dependencies {
        ......
        compile files('libs/alipaySdk-20170725.jar')
        ......
    }

    2.修改AndroidManifest.xml 和 权限声明

     <activity
                android:name="com.alipay.sdk.app.H5PayActivity"
                android:configChanges="orientation|keyboardHidden|navigation"
                android:exported="false"
                android:screenOrientation="behind">
            </activity>
            <activity
                android:name="com.alipay.sdk.auth.AuthActivity"
                android:configChanges="orientation|keyboardHidden|navigation"
                android:exported="false"
                android:screenOrientation="behind">
            </activity>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    3.可以添加混淆规则

    -keep class com.alipay.android.app.IAlixPay{*;}
    -keep class com.alipay.android.app.IAlixPay$Stub{*;}
    -keep class com.alipay.android.app.IRemoteServiceCallback{*;}
    -keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
    -keep class com.alipay.sdk.app.PayTask{ public *;}
    -keep class com.alipay.sdk.app.AuthTask{ public *;}
    -keep class com.alipay.sdk.app.H5PayCallback {
        <fields>;
        <methods>;
    }
    -keep class com.alipay.android.phone.mrpc.core.** { *; }
    -keep class com.alipay.apmobilesecuritysdk.** { *; }
    -keep class com.alipay.mobile.framework.service.annotation.** { *; }
    -keep class com.alipay.mobilesecuritysdk.face.** { *; }
    -keep class com.alipay.tscenter.biz.rpc.** { *; }
    -keep class org.json.alipay.** { *; }
    -keep class com.alipay.tscenter.** { *; }
    -keep class com.ta.utdid2.** { *;}
    -keep class com.ut.device.** { *;}

    **4. 接下来就是调用支付宝的接口。PayTask对象主要为商户提供订单支付、查询功能,及获取当前开发包版本号。
    获取PayTask支付对象调用支付(支付行为需要在独立的非ui线程中执行),代码示例:**

    final String orderInfo = info;   // 订单信息(app支付请求参数字符串,主要包含商户的订单信息,key=value形式,以&连接。)
            Runnable payRunnable = new Runnable() {
    
                @Override
                public void run() {
                    PayTask alipay = new PayTask(DemoActivity.this);
                    String result = alipay.payV2(orderInfo,true);
    
                    Message msg = new Message();
                    msg.what = SDK_PAY_FLAG;
                    msg.obj = result;
                    mHandler.sendMessage(msg);
                }
            };
             // 必须异步调用
            Thread payThread = new Thread(payRunnable);
            payThread.start();

    这里写图片描述

    orderInfo 示例如下,参数说明见”请求参数说明”,orderStr的获取必须来源于服务端:

    app_id=2015052600090779&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22seller_id%22%3A%22%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.02%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%22314VYGIAGG7ZOYY%22%7D&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2016-08-15%2012%3A12%3A15&version=1.0&sign=MsbylYkCzlfYLy9PeRwUUIg9nZPeN9SfXPNavUCroGKR5Kqvx0nEnd3eRmKxJuthNUx4ERCXe552EV9PfwexqW%2B1wbKOdYtDIb4%2B7PL3Pc94RZL0zKaWcaY3tSL89%2FuAVUsQuFqEJdhIukuKygrXucvejOUgTCfoUdwTi7z%2BZzQ%3D

    5.支付结果获取和处理

    同步返回
    商户应用客户端通过当前调用支付的Activity的Handler对象,通过它的回调函数获取支付结果。(可参考alipay_demo实现)
    代码示例:

    private Handler mHandler = new Handler() {
             switch (msg.what) {
    
                    case 1:
    
                        Result result = new Result((String)msg.obj); //回掉的结果
                        String message = payResult.getMemo(); 
                        String resultStatus = payResult.getResultStatus();//对应的支付结果
                        String result = payResult.getResult();
                        if (resultStatus.equals("9000")) {
                            SDToast.showToast("支付成功");
                        } else if (resultStatus.equals("8000")) {
                            SDToast.showToast("支付结果确认中");
                        } else if (resultStatus.equals("4000")) {
                            SDToast.showToast(message);
                        } else {
                            // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                            SDToast.showToast("支付失败");
                        }
                        break;
    
                }
        };

    到这里就结束了,写的不好请见谅。。。。。。。。跪谢!!!!!!

    展开全文
  • Arcgis for Android 集成(二) AndroidStudio 之前介绍了Eclipse的集成步骤,现在说一下Studio的集成: 1.在Eclipse集成中介绍的方法中获取jar包和.so文件,复制到工程中,并引用: 2.在manifest.xml 文件中...
  • Android集成PayPal支付

    千次阅读 热门讨论 2016-05-26 16:38:57
    Android集成PayPal支付一、注册PayPal商家账户网址:https://www.paypal.com二、环境集成1、下载SDK:https://developer.paypal.com/docs/classic/lifecycle/sdks/ 2、导入jar包,此SDK还用到了okhttp、okio,...
  • NDK r21b 编译FFmpeg 、x264 提供Android集成 在现今这个阶段,越来越多的app会涉及到音视频,那么学会使用ffmpeg和x264就很有必要了。本篇文章将讲解如何把ffmpeg、x264编译成动态库和静态库。 1. 编译环境 ...
  • android 集成Facebook 分享功能

    千次阅读 2017-08-11 13:12:30
    开场白 依然给大脸书承接上一篇 android 集成facebook的登录功能首先分享功能 要在清单文件中添加如下内容提供者:<provider android:authorities="com.facebook.app.FacebookContentProvider{APP_ID}" android:...
  • 有很长一段时间没有更新博客了,最近实在是太忙了,没有时间去总结,现在终于可以有时间去总结一些Android上面的东西了,很久以前写过这篇关于使用Android Studio搭建Android集成开发环境,不过一直没有发表出来,写...
  • android集成语音功能

    千次阅读 2016-01-14 18:07:00
    android集成语音功能 ONE Goal , ONE Passion ! 第1步: 预备工作导入SDK 将开发工具包中libs目录下的Msc.jar和armeabi复制到Android工程的libs目录(如果工程无libs目录,请自行创建)中, 如下图所示—eclipse:...
  • Android集成了VLC做实时预览,预览画面下方在7.0系统出现黑框?什么原因?
  • Android集成华为推送

    千次阅读 2018-08-30 17:35:13
    Android集成华为推送 1.注册成为开发者 这个没什么好讲的,照做就行了。之后就是在控制台创建应用巴拉巴拉的 需要注意的是SHA256指纹: SHA256你在控制台可以填好几个,博主建议填两个。一个是debug...
  • Android 集成支付宝支付详解

    万次阅读 2016-06-14 10:41:10
    Android 集成支付宝支付详解 一说到支付宝,相信没有人不知道,生活中付款,转账都会用到。 今天来详细介绍下在android中如何集成支付宝支付到自己的APP中去。让APP能够拥有方便,快捷的支付功能。 准备工作: ...
  • Android集成科大讯飞SDK

    千次阅读 2018-05-01 22:32:47
    Android集成科大讯飞SDK 上一篇文章为大家讲解了如何成为科大讯飞开发者,以及如何下载科大讯飞SDK;今天为大家讲解如何将我们下载好的SDK集成到Android项目中去。首先我们刚解压好的SDK是这个样子的。1、打开...
  • Android 集成 OpenCV native library

    千次阅读 2017-04-10 18:23:12
    Android集成OpenCV native library: 目前来看,OpenCV提供的SDK中已经附带了编译好的.a和.so库,使用者可以根据自己的需要选择动态或者静态库链接。 OpenCV SDK下载地址: http://opencv.org/releases.html 选择对应...
  • android 集成weex

    千次阅读 2018-10-24 20:20:28
    weex官网最新开发文档:https://weex.apache.org/guide/develop/integrate-to-android-app.html android集成weex: 1》、gradle: minSdkVersion 16 大于16 implementation ...
  • Android 集成华为推送 push

    千次阅读 2018-10-09 12:30:11
    这里引用:Android集成华为推送踩坑问题总结 使用老版push还是新版push PushReceiver中的onEvent()回调触发问题 APP接收到推送后,点击消息,总是会先打开启动页 如何自定义动作intent 如何解决请跳转链...
  • 极光推送Android集成以及使用

    千次阅读 2018-05-24 16:58:42
    极光推送Android集成以及使用(本文只集成了通知,如需要自定义消息,富文本等请去查看官方文档)https://docs.jiguang.cn/   一、概念图   二、搭建环境以及集成 1. 官网注册,并创建应用,获取app_key 2....
  • android 集成腾讯bugly版本升级功能

    千次阅读 2018-04-09 23:04:01
    android 集成腾讯bugly版本升级功能 腾讯bugly,一种愉悦的开发方式,对于android移动端开发的版本升级功能,无论是全量更新还是热更新,都给我带来了方便。主要看一下是怎么集成的。开发工具所使用的是android ...
  • 【新手连载】一:使用Android Studio搭建Android集成开发环境 http://bbs.itcast.cn/forum.php?mod=viewthread&tid=87055&fromuid=150705 (出处: 传智播客论坛_传智播客旗下社区) 一、Android Studio简单介绍  ...
  • Android集成华为推送功能详细

    千次阅读 2018-11-17 13:20:07
    Android集成推送功能也算是有好几个SDK了,包括极光、个推、小米、百度云推送。但是真心感觉华为的文档写的太差,封装的也不好,别的开发文档看一两遍就能按照文档集成成功,而华为仔细看了几遍都没完全搞懂要干啥。...
  • Android 集成百度文字识别1.4.0

    千次阅读 2017-12-20 15:28:29
    Android 集成百度文字识别1.4.0百度AI开放平台开放了文字识别的服务,可实现一些通用文字,网络图片文字,各种卡证(身份证,银行卡,驾驶证,行驶证,车牌营业执照,通用票据)等的识别需求,简化输入操作。...
  • Android 集成海康威视监控 SDK,实现监控录像的查看

    万次阅读 热门讨论 2018-08-01 14:43:35
    Android 集成海康威视监控 SDK,实现监控录像的查看 配置 切换Android studio 到project目录下,分别将jar包与armeabi包复制进去lib文件夹下: 设置app bulid.gradle文件 主要是添加CPU限制 只支持32位 以及...
  • Android集成极光推送 的异常

    千次阅读 2016-09-17 13:21:59
    Android集成极光推送 的异常Android集成极光推送报错,细节方面导致程序报的异常,但方便有同学之后遇到,这里做个记录1.贴下报错信息:D/JPush: [JPushInterface] action:init - sdkVersion:2.1.5, buildId:298 E/...
  • Android集成百度定位以及导航详解

    万次阅读 2016-12-10 00:08:54
    Android集成百度定位以及导航详解    百度地图Android SDK 官方下载地址:  包括类参考、示例代码、开发包(基础地图、检索功能、LBS云检索和计算工具)    申请密钥教程:点击打开 1.无GUI定位:
  • android集成最新支付宝遇到的坑

    千次阅读 2016-03-23 17:19:29
    android集成支付宝支付 整体思路 第一步:根据最新的支付宝文档,
  • Android集成Sentry

    千次阅读 2018-10-22 07:14:40
    Sentry Android SDK构建于主Java SDK之上,支持所有相同的功能,配置选项等。将Android SDK的1.7.10版本添加到甚至不使用Proguard的示例应用程序中,仅将发布的.apk大小增加了大约200KB。 默认情况下,事件将缓冲到...
  • Android集成原生微信授权获取用户信息登录 我在项目中用到的是点击一个按钮发起微信授权请求的需求,首先判断是否安装微信,如果安装微信则进行用户授权,授权成功之后通过微信提供的接口获取openID等用户信息,...
  • Android集成腾讯Bugly和简单使用

    千次阅读 2017-12-22 10:13:22
    Android集成腾讯Bugly和简单使用App线上发布之后,时常遇到客户使用过程中遇到bug,而通常我们不可能去拿用户的手机查看日记,而服务器上又没有上传bug日记接口的小伙伴们十分苦恼这怎么查找bug所在位置,一款腾讯...
  • android集成facebook第三方登录(踩坑) 集成的过程请看官网:https://developers.facebook.com/docs/facebook-login/android/ (需要科学上网) 如果你的应用没有上架,那么只能用你申请facebook开发者的那个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,993
精华内容 10,397
关键字:

android集成