zoukankan      html  css  js  c++  java
  • Android之友盟多渠道打包与数据统计(非原创)

    文章大纲

    一、多渠道打包与数据统计介绍
    二、友盟实现多渠道打包实战
    三、友盟数据统计实战
    四、项目源码下载
    五、参考文章

     

    一、多渠道打包与数据统计介绍

      多渠道打包,相信很多同学都知道。在Android Studio中只要经过配置,就能打出对应市场的渠道包。打过包的同学可能都会有这样的感受:散热器疯狂地转、打包速度那叫一个慢。这时候除了无奈,还是无奈。
      app上线后,一般公司都希望跟踪app在市场上的使用情况。包括新增用户、活跃用户、渠道信息、错误信息等,还有例如商城类的app,需要跟踪用户最喜欢浏览哪种类型的店铺或商品
      针对上面问题,如果我们自己手动去一个个处理,那么会崩溃的,因此已经有相关第三方平台做好了这方面功能,我们进行集成即可。多渠道打包和数据统计的第三方有很多,在此我们使用友盟平台进行实战。

    二、友盟实现多渠道打包实战

    1. 接入前准备工作

    (1)获取AppKey

      集成【友盟+】SDK之前,您首先需要到 【友盟+】官网注册并且添加新应用,获得AppKey。

    特别提醒 :我们建议开发者在注册账号时使用企业邮箱,避免使用个人邮箱注册,防止由于个人离职带来的问题,建议使用的账号形式:umeng@企业域名、apps@企业域名、dev@企业域名。

     

    常见问题
    问题1 :应用的安卓版和iOS版能否共用一个AppKey。
    答案:不同平台的应用禁止使用相同的AppKey,需要分开注册。
    问题2 :注册应用时,提示应用名称已存在。
    答案 :【友盟+】后台的应用名与实际应用名和包名无关,建议命名为应用名+平台(iOS/Android)。

    (2)build.gradle添加相关配置

      在工程build.gradle配置脚本中buildscript和allprojects段中添加【友盟+】sdk 新maven仓库地址

    buildscript {
        
        repositories {
            google()
            jcenter()
            mavenCentral()
    
            //添加友盟相关的maven地址
            maven { url 'https://dl.bintray.com/umsdk/release' }
        }
        dependencies {
    
            classpath 'com.android.tools.build:gradle:3.1.2'
            
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            google()
            jcenter()
    
          //添加友盟相关的maven地址
            maven { url 'https://dl.bintray.com/umsdk/release' }
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    

    (3)工程build.gradle配置

       //添加友盟依赖
        implementation 'com.umeng.sdk:common:latest.integration'
        implementation 'com.umeng.sdk:analytics:latest.integration'
    

    (4)添加相关权限

    <!-- 必须的权限 -->
    <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.INTERNET" />
    
    <!-- 推荐的权限 -->
    <!-- 添加如下权限,以便使用更多的第三方SDK和更精准的统计数据 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    (5)AndroidManifest清单配置文件方式初始化appkey和channel

    <!--友盟统计appkey配置-->
            <meta-data android:value="实际项目在友盟的appkey" android:name="UMENG_APPKEY"/>
            <meta-data android:value="${UMENG_CHANNEL_VALUE}" android:name="UMENG_CHANNEL"/>
    

    (6)自定义Application

    public class MyApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
            /**
             * 初始化common库
             * 参数1:上下文,必须的参数,不能为空
             * 参数2:友盟 app key,非必须参数,如果Manifest文件中已配置app key,该参数可以传空,则使用Manifest中配置的app key,否则该参数必须传入
             * 参数3:友盟 channel,非必须参数,如果Manifest文件中已配置channel,该参数可以传空,则使用Manifest中配置的channel,否则该参数必须传入,channel命名请详见channel渠道命名规范
             * 参数4:设备类型,必须参数,传参数为UMConfigure.DEVICE_TYPE_PHONE则表示手机;传参数为UMConfigure.DEVICE_TYPE_BOX则表示盒子;默认为手机
             * 参数5:Push推送业务的secret,需要集成Push功能时必须传入Push的secret,否则传空
             */
            //如果AndroidManifest.xml清单配置中没有设置appkey和channel,则可以在这里设置
            //        UMConfigure.init(this, "58edcfeb310c93091c000be2", "Umeng", UMConfigure.DEVICE_TYPE_PHONE, "1fe6a20054bcef865eeb0991ee84525b");
            UMConfigure.init(this, UMConfigure.DEVICE_TYPE_PHONE,"");
        }
    }
    
    

    2. 实现多渠道打包代码

    (1)添加多渠道打包

    //多渠道打包支持
    
        productFlavors {
            Alpha {
                applicationId "info.xinfu.o2o"//设置包名
                versionCode 2
                versionName "3.1"//设置版本号
            }//自己打包测试使用
            Tencent {}//投放应用宝市场
            Baidu {
                versionCode 1
                versionName "3.0"
            }//投放百度市场
            Wandoujia {}//投放豌豆荚市场
            PP {}//投放PP助手市场
            Qihoo {}//投放PP助手市场
            Vivo {}//投放vivo市场
            Oppo {}//投放oppo市场
            Xiaomi {}//投放小米市场
            Meizu {}//投放魅族市场
            Huawei {}//投放华为应用市场
            Lenovo {}//投放联想市场
            Letv {}//投放乐视市场
            Gionee {}//投放金立市场
            HiMarket {}//投放安卓市场
    
            //manifestPlaceholders 使用相关的值替换了UMENG_CHANNEL_VALUE
            productFlavors.all {
                flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
            }
    

    更新项目时候出现异常
      当我们更新项目时候,可能会出现以下异常

    Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
    

    解决办法如下:

    defaultConfig {
          ...
          //版本名后面添加一句话,意思就是flavor dimension 它的维度就是该版本号,这样维度就是都是统一的了
            flavorDimensions "versionCode"
        }
    

    (2)配置完成后project的build.gradle

    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    
    buildscript {
        
        repositories {
            google()
            jcenter()
            mavenCentral()
    
            //添加友盟相关的maven地址
            maven { url 'https://dl.bintray.com/umsdk/release' }
        }
        dependencies {
    
    
            classpath 'com.android.tools.build:gradle:3.1.2'
            
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            google()
            jcenter()
            //添加友盟相关的maven地址
            maven { url 'https://dl.bintray.com/umsdk/release' }
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    
    

    (3)配置完成后app的build.gradle

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 28
        defaultConfig {
            applicationId "com.example.wxc.testpackage"
            minSdkVersion 15
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
            //解决Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html异常
            flavorDimensions "versionCode"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    
        //多渠道打包支持
        productFlavors {
            Alpha {
                applicationId "info.xinfu.o2o"//设置包名
                versionCode 2
                versionName "3.1"//设置版本号
            }//自己打包测试使用
            Tencent {}//投放应用宝市场
            Baidu {
                versionCode 1
                versionName "3.0"
            }//投放百度市场
            Wandoujia {}//投放豌豆荚市场
            PP {}//投放PP助手市场
            Qihoo {}//投放PP助手市场
            Vivo {}//投放vivo市场
            Oppo {}//投放oppo市场
            Xiaomi {}//投放小米市场
            Meizu {}//投放魅族市场
            Huawei {}//投放华为应用市场
            Lenovo {}//投放联想市场
            Letv {}//投放乐视市场
            Gionee {}//投放金立市场
            HiMarket {}//投放安卓市场
    
            //manifestPlaceholders 使用相关的值替换了UMENG_CHANNEL_VALUE
            productFlavors.all {
                flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    
        //添加友盟依赖
        implementation 'com.umeng.sdk:common:latest.integration'
        implementation 'com.umeng.sdk:analytics:latest.integration'
    
    }
    
    

    (4)配置完成后的AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.wxc.testpackage">
    
        <!-- 必须的权限 -->
        <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.INTERNET" />
    
        <!-- 推荐的权限 -->
        <!-- 添加如下权限,以便使用更多的第三方SDK和更精准的统计数据 -->
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
        <application
            android:name=".MyApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
    
            <!--友盟统计appkey配置-->
            <meta-data android:value="5cac9da40cafb2a2bd00148e" android:name="UMENG_APPKEY"/>
            <meta-data android:value="${UMENG_CHANNEL_VALUE}" android:name="UMENG_CHANNEL"/>
    
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    (5)添加多渠道信息统计

      即启动数据的统计(包括新增用户、活跃用户、启动次数、使用时长等基本数据)
      需要在每个Activity的onResume方法中调用 MobclickAgent.onResume(Context),
    onPause方法中调用 MobclickAgent.onPause(Context),如下:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            MobclickAgent.onResume(this);
    
            Button button = findViewById(R.id.checkButton);
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    Toast.makeText(MainActivity.this, "点击了", Toast.LENGTH_SHORT).show();
    
                    MobclickAgent.onEvent(MainActivity.this, "checkButton");//参数二为当前统计的事件ID
    
                }
            });
        }
    
        protected void onPause() {
            super.onPause();
            MobclickAgent.onPause(this);
        }
    }
    

    温馨提示:
    (1)如果Activity之间有继承或者控制关系请不要同时在父和子Activity中重复添加nPause和nResume方法,否则会造成重复统计。例如在BaseActivity中添加过,则它的子类就不需要添加了。
    (2)当应用在后台运行超过30秒(默认)再回到前端,将被认为是两个独立的session(启动),例如用户回到home,或进入其他程序,经过一段时间后再返回之前的应用。可通过接口:setSessionContinueMillis(long interval) 来自定义这个间隔(参数单位为毫秒)。
    (3)如果开发者调用kill或者exit之类的方法杀死进程,请务必在此之前调用onKillProcess(Context context)方法,用来保存统计数据。

    (6)项目打包

    选择Generate Signed APK

     

    新建一个签名文件

     

    填写信息

     
     
     

    补充说明:
    (1)android 7.0中引入了APK Signature Scheme v2,v1呢是jar Signature来自JDKV1:应该是通过ZIP条目进行验证,这样APK 签署后可进行许多修改 - 可以移动甚至重新压缩文件。(2)V2:验证压缩文件的所有字节,而不是单个 ZIP 条目,因此,在签名后无法再更改(包括 zipalign)。正因如此,现在在编译过程中,我们将压缩、调整和签署合并成一步完成。好处显而易见,更安全而且新的签名可缩短在设备上进行验证的时间(不需要费时地解压缩然后验证),从而加快应用安装速度。v1和v2的签名使用:
    (4)只勾选v1签名并不会影响什么,但是在7.0上不会使用更安全的验证方式,只勾选V2签名7.0以下会直接安装完显示未安装,7.0以上则使用了V2的方式验证。同时勾选V1和V2则所有机型都没问题

    运行结果如下所示:

     

    (7)运行结果

     

    当我们用手机安装apk后,在友盟后台可看到以下统计

     

    三、友盟数据统计实战

    1. 自定义点击事件

      自定义事件可以实现在应用程序中埋点来统计用户的点击行为。例如我们的应用需要统计用户是点击了“,还是cheackButton按钮。自定义事件目前包括"计数事件"和"计算事件",这里主要讲下计数事件。
    1、首先需要在友盟后台添加自定义事件:设置-事件-手工添加-添加事件。如下:

     

    在需要统计位置中加入以下代码

    button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    Toast.makeText(MainActivity.this, "点击了", Toast.LENGTH_SHORT).show();
    
                    MobclickAgent.onEvent(MainActivity.this, "checkButton");//参数二为当前统计的事件ID
    
                }
            });
    

    运行程序后,在友盟后台可看到以下结果

     

    2. 错误统计

      组件化统计SDK内建JVM层错误统计。SDK通过Thread.UncaughtExceptionHandler 捕获程序崩溃日志,并在程序下次启动时发送到服务器。
      如不需要错误统计功能,可通过此方法关闭:

    // isEnable: false-关闭错误统计功能;true-打开错误统计功能(默认打开)
    public static void setCatchUncaughtExceptions(boolean isEnable)
    

    参数 含义
    isEnable 错误统计开关,false-关闭错误统计功能;true-打开错误统计功能(默认打开)。
    如果开发者自己捕获了错误,需要手动上传到【友盟+】服务器可以调用下面方法:

    代码:复制代码到剪切板
    public static void reportError(Context context, String error);   
    //或  
    public static void reportError(Context context, Throwable e);
    

    参数 含义
    context 当前宿主进程的ApplicationContext上下文。
    error 错误内容字符串。
    e 错误发生时抛出的异常对象。

    3.总结

      友盟还提供了其他的统计方法,包括页面统计、账号统计等,具体的功能事情请参考友盟的开发者文档:
    https://developer.umeng.com/docs/66632/detail/101848#h2-u9519u8BEFu7EDFu8BA111

    四、项目源码下载

    链接:https://pan.baidu.com/s/1sUKsyJUNQLJ4j65_ZxkNZQ
    密码:yvqs

    五、参考文章

    1. https://www.jianshu.com/p/e4da2f477cd8
    2. https://www.jianshu.com/p/e4da2f477cd8
    3. https://www.jianshu.com/p/3acba4233bc6
    4. https://www.jianshu.com/p/476ba5953d94
     
  • 相关阅读:
    spring管理hibernate,mybatis,一级缓存失效原因
    The constructor ClassPathXmlApplicationContext(String) refers to the missing type BeansException
    idea中Hibernate错误:无法解析表
    使用Dom4解析xml
    关于idea中新建web项目 webapp文件夹没有小蓝点 ,启动服务,访问不到解决方案
    解决VS编译太慢问题
    Entity FrameWork6 Code First带virtual关键字外键 Asp.Net WebApi无法返回实体类数据问题
    webapi请求返回{"$id":"1","Message":"请求的资源不支持 http 方法“GET”。"}
    WPF的BusyIndicator控件只显示遮罩层,不显示提示层问题
    [转]Mysql将数据分组后取出时间最近的数据
  • 原文地址:https://www.cnblogs.com/WUXIAOCHANG/p/10683942.html
Copyright © 2011-2022 走看看