Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
<uses-permission android:name="android.permission.INTERNET"/> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 
<uses-permission android:name="android.permission.GET_TASKS"/> 
<uses-permission android:name="android.permission.READ_LOGS"/> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


 
         2)权限说明

权限用途
ACCESS_NETWORK_STATE(必须)允许检测网络连接状态,在网络不好的状态下避免数据发送,节省流量和电量
READ_PHONE_STATE(必须)允许访问手机设备的信息,通过获取的IMEI信息来唯一标识用户
ACCESS_WIFI_STATE(必须)允许获取手机设备的WiFi Mac地址,在平板设备上,无法通过IMEI标识设备,我们会将WiFi Mac地址作为用户唯一标识
INTERNET(必须)允许程序联网,以便向我们的服务器端发送数据
ACCESS_FINE_LOCATION(必须)允许程序获取设备的位置信息(如GPS信息)
WRITE_EXTERNAL_STORAGE(必须)允许程序获得外部存储写入权限,用于保存设备信息和日志记录
GET_TASKS(必须)允许程序获取设备当前或最近运行的任务
READ_LOGS(必须)允许程序读取底层系统日志文件


1.4 添加引用

 在使用cobub sdk函数的Activity文件头中,添加引用 import com.wbtech.ums.UmsAgent;

1.5 初始化sdk

  • 在Android应用的入口Activity的onCreate()方法中调用UmsAgent.init(Context context, String url,String AppKey)方法,注意这个方法应置于所有其他的方法之前。url为自行安装的Cobub Razor服务端地址,注意地址以index.php?/ums结束,如:"http://demo.cobub.com/razor/index.php?/ums"。

    Code Block
    @Override
     public void onCreate(Bundle savedInstanceState) {
        ...
        UmsAgent.init(this,"http://demo.cobub.com/razor/index.php?/ums", "your appkey");
     }

    注:如果同时使用了其他统计SDK,如果cobub先注册,其他错误统计后注册,会导致cobub的自动捕捉错误统计被覆盖而无数据。同理应用内如果有捕捉错误信息的代码(实现了UncaughtExceptionHandler类),建议注释掉!

    完成初始化配置之后,集成了Cobub SDK的应用可以运行,并搜集到最基本的统计数据,如活跃用户、新增用户、启动次数以及设备相关的统计等。如需更详细的统计,则需继续集成后续章节的代码。

 

  • 参数配置

           通过本模块的集成操作,你可以进行一些关于SDK的参数配置,包含:

                  1.数据发送模式;

                  2.数据发送间隔时长;

                  3.是否发送位置信息;

                  4.session存活时长;

                  5.缓存文件大小;

                  6.是否只在wifi状态下更新。

            有两种方式配置sdk的相关参数。

       2.1  本地配置

        1)设置数据发送模式(默认情况下为实时发送)

              提供三种种数据发送模式 实时发送、下次启动发送和定时发送模式,通过如下方法可以设置数据的发送模式。

Code Block
UmsAgent.setDefaultReportPolicy(Context context, SendPolicy.POST_ONSTART); //下次启动发送
UmsAgent.setDefaultReportPolicy(Context context, SendPolicy.POST_NOW);     //实时发送
UmsAgent.setDefaultReportPolicy(Context context,SendPolicy.POST_INTERVAL); //按时间间隔发送

   模式解释

  • 启动时发送
    应用程序每次只会在启动时向服务器发送一次消息,在应用程序过程中产生的所有消息都会在下次启动时候发送。如果应用程序启动时处在不联网状态,那么消息将会缓存在本地,下次再尝试发送。
  • 实时发送(推荐使用)
    应用程序每产生条消息时,就立即发送到服务器。这种方式使得计算更及时
  • 间隔发送
    按时间间隔发送,默认的时间间隔为1min。如果需要修改该时间间隔,可以通过如下函数修改:
    UmsAgent.setPostIntervalMillis(Context context, long interval); 参数 interval的时间单位为:ms。


         2)设置数据发送间隔时长

               前提:数据发送格式设置为了按时间间隔发送。默认的时间间隔为1min发送一次。如果需要修改该时间间隔,可以通过如下方法修改:

Code Block
UmsAgent.setPostIntervalMillis(Context context, long interval); //参数interval的时间单位为:毫秒。


         3)设置是否发送位置信息

               该方法用来设置客户端是否发送用户的位置信息。在程序中调用如下方法来设置是否发送位置信息:

Code Block
UmsAgent.setAutoLocation(boolean isSendLocation); //true:发送;false:不发送。默认false,不发送。


         4)设置session存活时间

              用于统计启动次数,两次启动程序的间隔超过设置的时长时,第二次打开应用会生成一个新的session,视为第二次启动。否则两次打开应用的操作视为一次启动。在程序                 中调用如下方法设置session的存活时间,默认时间为30s。
Code Block
UmsAgent.setSessionContinueMillis(Context context,long interval); //参数interval的时间单位为:毫秒。默认30s。

          5)设置日志缓存文件大小

                SDK未提供该方法,只能通过修改源码属性或者使用在线配置。

        2.2 在线配置

                启用在线配置参数方法如下(需要在web端开启在线配置功能,并进行相应参数配置):

Code Block
UmsAgent.updateOnlineConfig(Context context); //在后台进行相关配置后,即可获取并应用在线配置

 

  • 页面统计

          通过本模块的集成操作,即可统计到页面访问路径,页面访问时长等信息。如需更详细的统计,则需继续集成后续章节的代码。

       3.1 Activity页面统计

               在Android应用的每个Activity页面文件的onResume()和onPause()函数中添加代码如下,以便追踪并统计页面的相关信息:

Code Block
@Override
protected void onResume(){
super.onResume();
UmsAgent.onResume(this);
}
@Override
protected void onPause(){
super.onPause();
UmsAgent.onPause(this);
}

         3.2 Web页面访问统计

                  Cobub Razor的Android SDK同时提供了针对Web页面的统计,在加载WebView控件(或继承了WebView控件的第三方控件)控件的Activity界面中,重写                                           onPageFinished() 方法,添加代码:

Code Block
WebView webview = (WebView)findViewById(R.id.webView1);
webview.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url)
{ super.onPageFinished(view, url);
//在此需截取url中的有效页面名称,防止因参数不同而将同一页面重复统计
UmsAgent.postWebPage(url);
}
});

         3.3 fragment 页面统计

                 由于现在的应用很多都是有少数的Activity加大量的Fragment组成,因此我们在统计中增加了对Fragment页面的统计。
                 app页面的常见使用场景如下:

    上图为三种典型的页面统计场景

  1. 纯粹基于 Activity 的页面
  2. Activity中包含 Fragment 的页面(也有可能是Fragment包含Fragment)
  3. Activity 中包含多个并列 Fragment 的页面

    在上述场景中, 我们可以统计到的页面为:
      1.A activity -> B activity ->C activity;
      2.A activity -> B activity ->Fragment 2;
      3.A activity -> B activity ->Fragment 3;
      4.A activity -> Fragment 1 ->C activity;
      5.A activity -> Fragment 1 ->Fragment 2;
      6.A activity -> Fragment 1 ->Fragment 3;
   如下的顺序目前是无法统计到的:
      A activity > B activity ->C activity>Fragment 2;
      A activity > B activity ->C activity>Fragment 3;
   如果页面是使用FragmentActivity + Fragment实现的,需要在 FragmentActivity 中统计时长:

1)针对无ViewPager:

Code Block
public class Fragment2 extends Fragment {
@Override
 public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
 }

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    return inflater.inflate(R.layout.fragment2, container, false);
 }
 @Override
 public void onPause() {
    // TODO Auto-generated method stub
     super.onPause();
     UmsAgent.onPause(activity);
 }
@Override
 public void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    UmsAgent.onFragmentResume(activity, "Fragment 2");
 }
 Activity activity;
 @Override
 public void onAttach(Activity activity) {
        super.onAttach(activity);
    this.activity = activity;
 }
}

2)针对有ViewPager:(注意:不用在onPause方法中调用)

          首先在onResume方法中调用如下方法:

Code Block
@Overridepublic void onResume() {
// TODO Auto-generated method stub
super.onResume();
UmsAgent.onFragmentResume(getActivity(), "Fragment—名字");
}

          然后在onHiddenChanged 方法中调用如下方法:

Code Block
@Override public void onHiddenChanged(boolean hidden) {
// TODO Auto-generated method stub
super.onHiddenChanged(hidden);
if(hidden){
UmsAgent.onPause(getActivity());
}else{
UmsAgent.onFragmentResume(getActivity(), "fragment—名字");
}
}

 

  • App自动更新

 
          在入口Activity的onCreate()方法中调用如下方法,应用程序将自动检测服务端是否有新的版本。

         机制说明:

          每次更新Android应用程序,您只需要修改VersionCode,把Android应用程序的apk文件上传到服务器。UmsAgent.update(Context context)方法会判断是否有新版应用程序,           如果发现可更新的应用程序安装包,会提示用户是否更新。用户选择更新后,安装包会下载安装更新。(根据version code来检测是否需要更新

 

Code Block
UmsAgent.update(this); //启用app新版本自动更新功能

          相关方法:UmsAgent.setUpdateOnlyWifi(boolean); //是否只在wifi状态下更新。

          在调用update()方法前调用setUpdateOnlyWifi()方法设置是否只在wifi状态下更新,默认为true,即只在wifi状态下更新!

  • 自定义参数接口

           
Code Block
updateCustomsParameters();      //获取在线配置参数 保存到本地
getConfigParameter(String key); //获取本地保存的在线配置参数

          必须先调用方法updateCustomsParameters();将获取到的自定义参数缓存到本地,然后使用getConfigParameter(String key)获取指定的key对应的自定义值。

           updateCustomsParameters()方法返回值格式:

{ reply: {returnCode: {domain: null, type: "S", code: "AAAAAA" }, parameters: [ { key: "showad", value: "1" }, { key: "display_menu", value: "1" } ] } }

 

...

           SDK提供了调试的功能,在应用集成调试过程中,可以调用以下接口打开日志进行查看:

Code Block
UmsAgent.setDebugEnabled(boolean isEnableDebug); //是否打开调试功能
UmsAgent.setDebugLevel(LogLevel); //定义SDK的log输出等级
LogLevel的定义如下:
public enum LogLevel {
Info, // equals Log.INFO, for less important info
Debug, // equals Log.DEBUG, for some debug information
Warn, // equals Log.WARN, for some warning info
Error, // equals Log.ERROR, for the exceptions errors
Verbose // equals Log.VERBOSE, for the verbose info
}

           注意:在打包发布前请将日志功能关闭。

 
  • H5页面数据统计

             在JavaScript中调用jar包中的原生方法(针对H5页面)

        6.1 封装一个Java类 如 JSUMSAgent (SDK 中已经提供该类)

 
Code Block
import android.content.Context;public class JSUMSAgent {
 Context context;
public JSUMSAgent(Context context) {
 super();
 this.context = context;
 }
 public void bindUserIdentifier(String identifier){
 UmsAgent.bindUserIdentifier(context, identifier);
 }
   
 public void onError(String errorInfo){
 UmsAgent.onError(context, errorInfo);
   
 }
  
 public void postTags(String tags){
 UmsAgent.postTags(context, tags);
 }
   
 public void onEvent(String event_id){
 UmsAgent.onEvent(context, event_id);
 }
   
 public void onEvent(String event_id, int acc){
 UmsAgent.onEvent(context, event_id, acc);
 }
 public void onEvent(String event_id,
 String label, int acc) {
 UmsAgent.onEvent(context, event_id, label, acc);
 }
 public void onEvent( String event_id,
 String label, String json) {
 UmsAgent.onEvent(context, event_id, label, json);
 }
 public void onGenericEvent(String label,String value){
 UmsAgent.onGenericEvent(context, label, value);
 }
 public void postWebPage(String pageName){
    UmsAgent.postWebPage(pageName);
 }
}


 
       6. 2 在入口activity中创建该对象,同时将该对象传递到JavaScript中

 
Code Block
mWebView=(WebView)findViewById(R.id.wv_test);JSUMSAgent jsUmsAgent = new JSUMSAgent(this);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(jsUmsAgent , "umsagent");// 如果HTML页面放到了服务端,IOS和Android使用一套页面别名需要统一为umsagent如果HTML页面放到了服务端,IOS和Android使用一套页面别名需要统一为umsagent 


         6.3 在JavaScript中通过umsagent调用对应的方法。

 
Code Block
 umsagent.onEvent(event_id);
      
       6.4 WebView注入Java对象注意事项

                 在android4.2以前可以采用以上的方式直接注入Java对象,在android4.2之后注入对象的方法要加注释语句@JavascriptInterface
               如下:

 
Code Block
public class JSUMSAgent { Context context;
public JSUMSAgent(Context context) {
 super();
 this.context = context;
 }
 @JavascriptInterface
 public void bindUserIdentifier(String identifier){
 UmsAgent.bindUserIdentifier(context, identifier);
 }
 @JavascriptInterface
 public void onError(String errorInfo){
 UmsAgent.onError(context, errorInfo);
   
 }
 @JavascriptInterface
 public void postTags(String tags){
 UmsAgent.postTags(context, tags);
 }
 @JavascriptInterface
 public void onEvent(String event_id){
 UmsAgent.onEvent(context, event_id);
 }
 @JavascriptInterface
 public void onEvent(String event_id, int acc){
 UmsAgent.onEvent(context, event_id, acc);
 }
 @JavascriptInterface
 public void onEvent(String event_id,
 String label, int acc) {
 UmsAgent.onEvent(context, event_id, label, acc);
 }
 @JavascriptInterface
 public void onEvent( String event_id,
 String label, String json) {
 UmsAgent.onEvent(context, event_id, label, json);
 }
 @JavascriptInterface
 public void onGenericEvent(String label,String value){
 UmsAgent.onGenericEvent(context, label, value);
 }
 @JavascriptInterface
 public void postWebPage(String pageName){
  UmsAgent.postWebPage(pageName);
 }
}


         经过查官方文档所知,因为这个接口允许JavaScript 控制宿主应用程序,这是个很强大的特性,但同时,在4.2的版本前存在重大安全隐患,因为JavaScript 可以使用反射访问注入webview 的java对象的public fields,在一个包含不信任内容的WebView中使用这个方法,会允许攻击者去篡改宿主应用程序,使用宿主应用程序的权限执行java代码。因此4.2以后,任何为JS暴露的接口,都需要加@JavascriptInterface

  
  • 代码混淆 

           代码混淆是请不要混洗jar包中的内容,请在混淆文件中添加:

             -keep class com.wbtech.ums.** {*;}

Info

注意事项

  • 权限
    确认所需的权限都已经添加
  • 联网检查
    确认测试手机或者模拟器已成功连入网络