A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小鲁哥哥 于 2017-6-17 14:53 编辑

【济南中心】Android课程同步笔记智慧北京:Day05(下)


软引用
内存缓存是通过一个HashMap来缓存数据的,当缓存大量的图片时,就是导致我们的应用程序出现内存溢出的情况。由于我们bitmap是在HashMap中属于强引用状态。而系统并不会回收强引用对象,为了解决这样的问题,我们可以缓存的bitmap对象,由原来的强引用状态变为软引用状态。当内存不足时,回收软用的bitmap对象。
Bitmap对象设置为软引用状态
[Java] 纯文本查看 复制代码
public class MemoryCacheUtils {    private static HashMap<String, SoftReference<Bitmap>> caches;
    static {
        //caches = new HashMap<>();//Android虚拟机的内存只有16M,产生OOM异常(内存溢出)
        //java语言提供了另外一种机制:软引用、弱引用、虚引用
        //软引用:当虚拟机内存不足的时候,回收软引用的对象
        //弱引用:当对象没有应用的时候,马上回收
        //虚引用 :任何情况下都可能回收
        //java默认的数据类型是强引用类型
        caches = new HashMap<>();
    }

    //写缓存
    public static void saveCache(Bitmap bitmap,String url){
        //将bitmap由强引用状态,设置软引用状态
        SoftReference<Bitmap> soft = new SoftReference<Bitmap>(bitmap);
        caches.put(url,soft);
    }
    //读缓存
    public static Bitmap readCache(String url){
        SoftReference<Bitmap> soft = caches.get(url);
        if(soft != null){
            Bitmap bitmap = soft.get();
            return bitmap;
        }
        return null;
    }
}

LruCache的使用和原理
从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象。因此使用软引用方式,变得更加不可靠,因此,google官方推荐我们使用这样一种缓存机制:LruCache。
什么是LruCache
l  使用最近最少算法机制。来缓存每个对象的。
l  把近期最少使用的数据从缓存中移除,保留使用最频繁的数据
l  LruCache内存维护一个LinkedHashMap,来维护每个缓存对象
l  从LruCache取出对象,它会把当前使用的对象进行移动到LinkedHashMap尾端
l  如果添加一个缓存对象,LruCache会把当前对象也放在LinkedHashMap尾端
l  在LinkedHashMap的顶端就是最近最少使用的缓存对象。也就是被移除的对象了。
LruCache使用
l  构建LruCache对象,同时指定内存缓存大小
l  重写内部的sizeOf方法,计算每个图片的大小
l  使用LruCache的put方法缓存对象

l  使用LruCache的get方法取出对象
[Java] 纯文本查看 复制代码
public class MemoryCacheUtils {

    static {

        //因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。
        long maxMemory = Runtime.getRuntime().maxMemory();//获取Dalvik 虚拟机最大的内存大小:16

        lruCache = new LruCache<String,Bitmap>((int) (maxMemory/8)){//指定内存缓存集合的大小
            //获取图片的大小
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight();
            }
        };
    }
    private static LruCache<String, Bitmap> lruCache;

    //写缓存
    public static void saveCache(Bitmap bitmap,String url){
        lruCache.put(url,bitmap);
    }
    //读缓存
    public static Bitmap readCache(String url){
        return lruCache.get(url);
    }
}
屏幕适配
一般开发中会先切两套图或者是一套图   
1 480*800
2 1280*720
但不是所有的图片都是需要切两套:
一般是向导界面 和应用的图标
软件开发的前期:一般都是不去考虑到屏幕适配的问题

如果出现屏幕适配器的问题,再通过其他的适配方式去搞定。
图片适配
屏幕适配方式
l  图片适配
l  布局适配
l  比重适配
l  dimens适配
l  代码适配

不同目录,代表的含义

不同目录,代表的含义:
mdpi、hdpi、xdpi、xxdpi:
用来修饰Android中的drawable/mipmap文件夹,用来区分不同像素密度下的图片
什么是像素密度?
屏幕像素密度是指每英寸上的像素点数,像素密度越大,显示画面细节就越丰富。单位是dpi
计算方式:
像素密度=√{(长度像素数^2+宽度像素数^2)}/ 屏幕尺寸
比如:分辨率为1280*720 屏幕宽度为6英寸。计算所得像素密度约等于245
名称    像素密度取值范围
mdpi     120dpi~160dpi
hdpi             160dpi~240dpi
xhdpi     240dpi~320dpi
xxhdpi   320dpi~480dpi
xxxhdpi 480dpi~640dpi
图片适配

把对应的分辨率的切换放入到对应的文件夹中:
比如:切图是分辨率为1280*720 屏幕宽度为6英寸。计算所得像素密度约等于245应该把图片放在对应的mipmap-xhdpi中。
系统在加载图片的时候,系统会自动根据设备的像素密度对图片进行加载。:
注意事项(补充)
Android系统默认寻找图片流程:

布局适配
res目录下创建不同分辨率下的布局文件夹,定义不同目录
Layout-480x320
这样的操作其实比较少,因为现在的软件都需要是软件界面需要统一

权重适配
在线性布局中,布局的宽高按照权重比例分配
权重比例:将剩余空间按比例分配,通过android:layout_weight属性进行指定
View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比
View的高度等于原有高度(android:layout_height)加上剩余空间的占比
操作
线性布局中,有两个子控件,两个子控件按照1:4显示。如下效果:
屏幕的宽度:L,View的原有宽度:2L,不同分辨率下适配效果:
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itheima.screenadapter_weight.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4"
        android:orientation="horizontal">
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#f00"></LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="4"
            android:background="#0f0"></LinearLayout>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#00f"></LinearLayout>
</LinearLayout>
注意事项(补充)
如果对线性布局中的控件设置了权重(layout_weight),那么控件占用的空间大小是可以计算出来的,计算公式如下:
线性布局中子控件最终占用宽度 = 原有宽度+剩余空间的占比
例如,在水平方向上的线性布局LinearLayout控件L中,包含两个水平占用空间的控件A、B,其中:
L控件:L控件宽度layout_width = width_l
A控件:A控件宽度layout_width = width_a   A控件权重layout_weight = weight_a
B控件:B控件宽度layout_width = width_b   B控件权重layout_weight = weight_b
L中子控件最终占用宽度 = 原有宽度(width_a)+剩余空间(L控件的宽度 – A控件的宽度- B控件的宽度)占比
A所占宽度 = width_a + (width_l-width_a-width_b)*weight_a/(weight_a+weight_b)
B所占宽度 = width_b + (width_l-width_a-width_b)*weight_b/(weight_a+weight_b)
由此可以推断,当使用权重(layout_weight)时,会遇到下列两种情况:
情况1:当L中内部子控件(A,B)的宽度之和大于L的总宽度时,即(width_l-width_a-width_b)<0时,weight_a/(weight_a+weight_b)比例的值越大,当前控件所占空间越小。
情况2:当L中内部子控件(A,B)的宽度之和小于L的总宽度时,即(width_l-width_a-width_b)>0时,weight_a/(weight_a+weight_b)比例的值越大,当前控件所占空间越大。
我们在使用的时候一般情况把要布局的一般吧width或者height设置为0dp
尺寸适配
概念:
在不同像素密度的设备,加载不同的尺寸文件中的值。
操作:
res目录下,创建不同尺寸的values文件夹,例如:
分别创建了分辨率为:320x240的values文件夹,并且在该目录下创建了dimens.xml文件:如图所示:
800x480的values文件夹,并且在该目录下创建了dimens.xml文件:如图所示:
当我们在程序中定义控件的宽度时,直接通过dimens文件中定义宽度来设置。系统会根据设备的分辨率,加载不同的dimens文件。当我们在布局文件中使用长或者宽度单位时,比如下图所示,应该使用@dimen/width来灵活的定义宽度。

注意事项(补充)
dimens.xml文件中定义的属性对应的值,单位dp。
Dp是dip的简写。其实dp就是dip。
dip: device independent pixels ,设备独立像素。
不同设备有不同的显示效果,这个和设备硬件有关。
Dip和px有什么区别?
px(pix):像素,就是屏幕中最小的一个显示单元,不同设备显示效果相同。
Google官方推荐:在做尺寸适配时,建议使用dip为单位,定义属性值。
另外一种的尺寸适配方式
可以根据像素密度设置特定的values目录让满足设定的设备进行加载。比如values-mdpi、values-hdpi、values-xhdpi、values-xxhdpi等等。然后每个目录放置一个demins.xml,使不同分辨率的设备应用不同的尺寸设置。使用@dimen/width来定义宽度应用设备在当前dpi对应目录的demins.xml中找到对应的值,进行适配。如果没有找到采用“就近匹配”原则。

代码适配
根据手机屏幕,计算布局的宽度为屏幕的1/4:
[Java] 纯文本查看 复制代码
//获取手机屏幕的宽度
int widthPixels = getResources().getDisplayMetrics().widthPixels;//宽度
int heightPixels = getResources().getDisplayMetrics().heightPixels;//高度

LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) ll.getLayoutParams();
params.width = widthPixels/4;
params.height = heightPixels;
//设置布局参数
ll.setLayoutParams(params);
与屏幕相关的参数

屏幕密度
[Java] 纯文本查看 复制代码
float density = getResources().getDisplayMetrics().density;//密度

Density : 指屏幕密度,每平方英寸中像素数
计算公式:Density  = DPI / 160
比如:


屏幕宽度为480, 高度为800 的手机
它的像素密度为:240
屏幕密度为:1.5
像素密度
[Java] 纯文本查看 复制代码
int densityDpi = getResources().getDisplayMetrics().densityDpi;//像素密度
[align=left]
DPI: 指像素密度,指每英寸上的像素数
计算公式:
像素密度=√{(长度像素数^2+宽度像素数^2)}/ 屏幕尺寸
比如:分辨率为1280*720 屏幕宽度为6英寸。计算所得像素密度约等于245

dp转px的使用
转换公式
如果实现dp和px进行转换:我们可以通过公式进行转换:
Px = dp * 屏幕密度 + 0.5f
Dp = px / 屏幕密度 + 0.5f
代码如下:


修改小灰点的宽度和高度
[Java] 纯文本查看 复制代码
private void initGrayPoint() {
    for (int resId : imgs) {
        View view = new View(this);
        view.setBackgroundResource(R.drawable.point_gray_bg);
        //原因:布局中红色点的单位:10dp   java代码中的10:是px
        //dp转换成px
        int width = Dp2PxUtils.dp2px(this,10);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width,width);
        params.rightMargin = 20;//设置右边距
        containerGrayPoint.addView(view,params);
    }
}
JPush推送集成
极光推送功能:
主动 即时的向用户发起交互,可以发送聊天信息等;
——作用:通过向精准的目标用户推送有价值的消息,可以提供用户的忠诚度,提高留存率。
推送方式
——发送通知:推送的文本内容,展示在通知栏上面;
——自定义消息:推送自定义消息,给用户自行处理;
——富媒体:推送的是HTML网页内容。
推送目标
——广播推送:向所有用户发送广播信息;
——标签推送 Tag:根据用户设置自定义的标签分组,向某一组推送消息;
——别名推送 Alias:客户端绑定用户自定义的用户别名,向单个用户推送消息。
极光推送的集成
1.打开极光推送官方网站
2.注册账号
3.创建客户端应用程序
4.在极光推送后台,添加应用程序
5.获取Appkey
6结合极光推送的集成文档进行集成
7.导入依赖的sdk和动态链接库so

8.配置清单文件
[XML] 纯文本查看 复制代码
<!-- Required -->
<permission
    android:name="com.itheima.jpushtest.permission.JPUSH_MESSAGE"
    android:protectionLevel="signature" />

<!-- Required -->
<uses-permission android:name="com.itheima.jpushtest.permission.JPUSH_MESSAGE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<!-- Optional. Required for location feature -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!-- Required SDK 核心功能-->
    <!-- option since 2.0.5 可配置PushService,DaemonService,PushReceiver,AlarmReceiver的android:process参数 将JPush相关组件设置为一个独立进程 -->
    <!-- 如:android:process=":remote" -->
    <service
        android:name="cn.jpush.android.service.PushService"
        android:enabled="true"
        android:exported="false" >
        <intent-filter>
            <action android:name="cn.jpush.android.intent.REGISTER" />
            <action android:name="cn.jpush.android.intent.REPORT" />
            <action android:name="cn.jpush.android.intent.PushService" />
            <action android:name="cn.jpush.android.intent.PUSH_TIME" />
        </intent-filter>
    </service>

    <!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。 -->
    <!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起 -->
    <service
        android:name="cn.jpush.android.service.DaemonService"
        android:enabled="true"
        android:exported="true">
        <intent-filter >
            <action android:name="cn.jpush.android.intent.DaemonService" />
            <category android:name="com.itheima.jpushtest"/>
        </intent-filter>
    </service>

    <!-- Required -->
    <receiver
        android:name="cn.jpush.android.service.PushReceiver"
        android:enabled="true" >
        <intent-filter android:priority="1000">
            <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />
            <category android:name="com.itheima.jpushtest"/>
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.USER_PRESENT" />
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
        <!-- Optional -->
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_ADDED" />
            <action android:name="android.intent.action.PACKAGE_REMOVED" />
            <data android:scheme="package" />
        </intent-filter>
    </receiver>
    <!-- Required SDK核心功能-->
    <activity
        android:name="cn.jpush.android.ui.PushActivity"
        android:configChanges="orientation|keyboardHidden"
        android:exported="false" >
        <intent-filter>
            <action android:name="cn.jpush.android.ui.PushActivity" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="com.itheima.jpushtest" />
        </intent-filter>
    </activity>
    <!-- Required SDK核心功能-->
    <service
        android:name="cn.jpush.android.service.DownloadService"
        android:enabled="true"
        android:exported="false" >
    </service>
    <!-- Required SDK核心功能-->
    <receiver android:name="cn.jpush.android.service.AlarmReceiver" />
    <!-- Required. For publish channel feature -->
    <!-- JPUSH_CHANNEL 是为了方便开发者统计APK分发渠道。-->
    <!-- 例如: -->
    <!-- 发到 Google Play 的APK可以设置为 google-play; -->
    <!-- 发到其他市场的 APK 可以设置为 xxx-market。 -->
    <!-- 目前这个渠道统计功能的报表还未开放。-->
    <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
    <!-- Required. AppKey copied from Portal -->
    <meta-data android:name="JPUSH_APPKEY" android:value="39eaf79b6402d5fcf896762b"/>

    <!-- User defined. 用户自定义的广播接收器-->
    <receiver
        android:name=".MyReceiver"
        android:enabled="true">
        <intent-filter>
            <!--Required 用户注册SDK的intent-->
            <action android:name="cn.jpush.android.intent.REGISTRATION" />
            <!--Required 用户接收SDK消息的intent-->
            <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />
            <!--Required 用户接收SDK通知栏信息的intent-->
            <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />
            <!--Required 用户打开自定义通知栏的intent-->
            <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />
            <!--Optional 用户接受Rich Push Javascript 回调函数的intent-->
            <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" />
            <!-- 接收网络变化 连接/断开 since 1.6.3 -->
            <action android:name="cn.jpush.android.intent.CONNECTION" />
            <category android:name="com.itheima.jpushtest" />
        </intent-filter>
    </receiver>
</application>
9.在Application初始化极光推送
[Java] 纯文本查看 复制代码
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        JPushInterface.setDebugMode(true);
        JPushInterface.init(this);
    }
}
10进入极光推送后台的推送消息模块,进行推送测试


极光推送的原理

推送框架
——推送的数据源:自己开发的服务器端或者使用极光推送官网的WEB后台;
——JPush API:部署在服务器端,开发者的服务器端发起推送时,将数据传到JPush
API中,然后向下传递;
——建立长链接:集成JPushSDK客户端启动后会建立一个到JPush Cloud的长链接,提供App永远在线的能力
推送流程
首先客户端集成JPush的sdk启动后,会通过Tcp协议建立一个到JPush Cloud的长链接,提供App永远在线的能力。
然后使用极光推送官网的WEB后台发起推送数据,将数据传到JPush API中,然后向下传递,传递给Push Engine
推送引擎将数据推送给客户端。

JPush发送自定义通知
配置用户自定义消息的广播接收器
[XML] 纯文本查看 复制代码
<!-- User defined. 用户自定义的广播接收器-->
<receiver
    android:name=".MyReceiver"
    android:enabled="true">
    <intent-filter>
        <!--Required 用户注册SDK的intent-->
        <action android:name="cn.jpush.android.intent.REGISTRATION" />
        <!--Required 用户接收SDK消息的intent-->
        <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />
        <!--Required 用户接收SDK通知栏信息的intent-->
        <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />
        <!--Required 用户打开自定义通知栏的intent-->
        <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />
        <!--Optional 用户接受Rich Push Javascript 回调函数的intent-->
        <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" />
        <!-- 接收网络变化 连接/断开 since 1.6.3 -->
        <action android:name="cn.jpush.android.intent.CONNECTION" />
        <category android:name="com.itheima.jpushtest" />
    </intent-filter>
</receiver>

自定义用户接受广播器
[Java] 纯文本查看 复制代码
public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        //发送的自定义消息
        if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
            Log.i(TAG,"发送的自定义消息");
            //获取数据
            Bundle bundle = intent.getExtras();
            String title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);
            String message = bundle.getString(JPushInterface.EXTRA_ALERT);
            String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
            JSONObject extrasJson = null;
            try {
                extrasJson = new JSONObject(extras);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            if(extrasJson != null){
                String url = extrasJson.optString("url");
                sendNotification(context,url,message);
            }

        }
    }

接受自定义消息
[Java] 纯文本查看 复制代码
if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
    Log.i(TAG,"发送的自定义消息");
    //获取数据
    Bundle bundle = intent.getExtras();
    String title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);
    String message = bundle.getString(JPushInterface.EXTRA_ALERT);
    String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
    JSONObject extrasJson = null;
    try {
        extrasJson = new JSONObject(extras);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    if(extrasJson != null){
        String url = extrasJson.optString("url");
        sendNotification(context,url,message);
    }
}

用户自定义发送消息通知
[Java] 纯文本查看 复制代码
//发送通知
public void sendNotification(Context context,String url,String message){
    //发送通知
    NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    //点击通知后激活的事件
    Intent i = new Intent();
    i.setAction(Intent.ACTION_VIEW);
    i.setData(Uri.parse(url));
    PendingIntent pendingIntent = PendingIntent.getActivity(context,100,i,0);

    //创建通知的Builder
    NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
    builder.setContentTitle("标题")//标题
            .setContentText(message)//内容
            .setContentIntent(pendingIntent)
            .setSmallIcon(R.drawable.jpush_notification_icon)//图标
            .setAutoCancel(true);//点击通知自动消失
    //发送通知
    nm.notify(1,builder.build());
}

友盟统计
友盟统计模块介绍定义
帮助移动应用开发商统计和分析流量来源、内容使用、用户属性和行为数据,以便开发商利用数据进行产品、运营、推广策略的决策
功能
新增用户统计
可以统计应用的新增用户、活跃用户、启动次数、版本分布、行业指标等数据,方便您从整体掌控应用的运营情况及增长动态
各渠道新增用户统计
可以实时查看各渠道的新增用户、活跃用户、次日留存率等用户指标,通过数据对比评估不同渠道的用户质量和活跃程度,从而衡量推广效果
留存率统计
可以掌握每日(周/月)的新增用户在初次使用后一段时间内的留存率,留存率的高低一定程度上反映了产品和用户质量的好坏
用户行为分析统计
针对性地进行应用内的数据统计,了解用户的产品使用细节及行为特征,帮助您寻找产品改进的突破点,评估产品优化的效果
错误日志分析
收集并归类崩溃日志,提供错误管理及分析工具,帮助开发者更好的解决问题,从而提高应用的稳定性,改善应用质量
友盟统计集成
准备工作
       注册账号
       申请AppKey
       创建应用
              个人中心
              基础统计
              添加应用

友盟SDK集成
1.添加依赖库:libs
2.配置清单文件:添加配置AppKey
[XML] 纯文本查看 复制代码
<meta-data android:value="57f76ce567e58e9dbf001409" android:name="UMENG_APPKEY"/>
<meta-data android:value="itheima" android:name="UMENG_CHANNEL"/>

3.基本统计

基本统计(session统计)
统计行为
              新增用户
              活跃用户
              使用时长
              启动次数
操作
[Java] 纯文本查看 复制代码
//友盟统计
public void onResume() {
    super.onResume();
    MobclickAgent.onResume(this);
}
//友盟统计
public void onPause() {
    super.onPause();
    MobclickAgent.onPause(this);
}

2 个回复

倒序浏览
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马