浏览代码

[콘텐츠][New] logging
- 1 contents 당 1회 로깅, 로깅 후 재 진입해도 다시 로깅하지 않는다.

hyodong.min 6 年之前
父节点
当前提交
643795809b

+ 19 - 5
app/src/common/java/kr/co/zumo/app/lifeplus/network/api/LifeplusAPIService.java

@@ -42,6 +42,8 @@ import kr.co.zumo.app.lifeplus.bean.api.ContentsBookmarkRequestBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsDetailResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsFlagResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsLikeRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRecordRequestBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRecordResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRequestBean;
@@ -162,18 +164,18 @@ public class LifeplusAPIService extends LifeplusRetrofitService implements Lifep
   /**
    * 위젯의 경우 파라메터 추가 없이 전송할 수 있다.
    *
-   * @param paramInterceptor
+   * @param headerInterceptor
    * @return
    */
-  private LifeplusAPI api(Interceptor paramInterceptor) {
+  private LifeplusAPI api(Interceptor headerInterceptor) {
     /**
      * 기본 timeout 설정 --------------------------
      */
-    return api(TIMEOUT_SHORT, paramInterceptor);
+    return api(TIMEOUT_SHORT, headerInterceptor);
   }
 
-  private LifeplusAPI api(int timeout, Interceptor paramInterceptor) {
-    return retrofit(getApiUrl(), LifeplusAPI.class, timeout, paramInterceptor);
+  private LifeplusAPI api(int timeout, Interceptor headerInterceptor) {
+    return retrofit(getApiUrl(), LifeplusAPI.class, timeout, headerInterceptor);
   }
 
   private LifeplusAPI api(int timeout) {
@@ -689,9 +691,21 @@ public class LifeplusAPIService extends LifeplusRetrofitService implements Lifep
    */
   @Override
   public Single<WidgetResultBean> getWidgetData(RequestBean bean) {
+    // 위젯은 헤더 없이 api 를 이용한다.
     return api(null).getWidgetData(bean);
   }
 
+  /**
+   * 콘텐츠 로그 남기기
+   *
+   * @param bean
+   * @return
+   */
+  @Override
+  public Single<ContentsLogResultBean> setContentsLog(ContentsLogRequestBean bean) {
+    return api(null).setContentsLog(bean);
+  }
+
   /**
    * 이벤트 리스트
    *

+ 25 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/bean/api/APIContentsLogModule.java

@@ -0,0 +1,25 @@
+/*
+ * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
+ */
+package kr.co.zumo.app.lifeplus.bean.api;
+
+import io.reactivex.Single;
+import kr.co.zumo.app.lifeplus.model.module.LifeplusAPIModule;
+import kr.co.zumo.app.lifeplus.network.api.LifeplusAPIRepository;
+
+/**
+ * APIContentsLogModule
+ * <pre>
+ * </pre>
+ *
+ * @author 민효동
+ * @version 1.0
+ * @history 민효동   [2019. 2. 26.]   [최초 작성]
+ * @since 2019. 2. 26.
+ */
+public class APIContentsLogModule extends LifeplusAPIModule<ContentsLogRequestBean, ContentsLogResultBean> {
+  @Override
+  protected Single<ContentsLogResultBean> getAPI(ContentsLogRequestBean requestBean) {
+    return new LifeplusAPIRepository().setContentsLog(requestBean);
+  }
+}

+ 36 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/bean/api/ContentsLogRequestBean.java

@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
+ */
+package kr.co.zumo.app.lifeplus.bean.api;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+/**
+ * ContentsLogRequestBean
+ * <pre>
+ * </pre>
+ *
+ * @author 민효동
+ * @version 1.0
+ * @history 민효동   [2019. 2. 26.]   [최초 작성]
+ * @since 2019. 2. 26.
+ */
+public class ContentsLogRequestBean extends ItemNoRequestBean {
+
+  @SerializedName("copsItemNoList")
+  private List<String> itemNoBeans;
+
+  public ContentsLogRequestBean(String itemNo) {
+    super(itemNo);
+  }
+
+  public List<String> getItemNoBeans() {
+    return itemNoBeans;
+  }
+
+  public void setItemNoBeans(List<String> itemNoBeans) {
+    this.itemNoBeans = itemNoBeans;
+  }
+}

+ 21 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/bean/api/ContentsLogResultBean.java

@@ -0,0 +1,21 @@
+/*
+ * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
+ */
+package kr.co.zumo.app.lifeplus.bean.api;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * ContentsLogResultBean
+ * <pre>
+ * </pre>
+ *
+ * @author 민효동
+ * @version 1.0
+ * @history 민효동   [2019. 2. 26.]   [최초 작성]
+ * @since 2019. 2. 26.
+ */
+public class ContentsLogResultBean extends LifeplusAPIBean {
+  @SerializedName("iResult")
+  private int result;
+}

+ 6 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/network/api/LifeplusAPI.java

@@ -42,6 +42,8 @@ import kr.co.zumo.app.lifeplus.bean.api.ContentsBookmarkRequestBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsDetailResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsFlagResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsLikeRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRecordRequestBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRecordResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRequestBean;
@@ -212,6 +214,10 @@ public interface LifeplusAPI {
   @POST("mapi/srch/getRecommendList.plus")
   Single<WidgetResultBean> getWidgetData(@Body RequestBean bean);
 
+  // 컨텐츠 로그
+  @POST("mapi/contents/inslogapp.plus")
+  Single<ContentsLogResultBean> setContentsLog(@Body ContentsLogRequestBean bean);
+
 
   /***********************************
    * Event

+ 7 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/network/api/LifeplusAPIRepository.java

@@ -44,6 +44,8 @@ import kr.co.zumo.app.lifeplus.bean.api.ContentsDetailResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsFlagBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsFlagResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsLikeRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRecordRequestBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRecordResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.EventAnswerRequestBean;
@@ -506,6 +508,11 @@ public class LifeplusAPIRepository implements LifeplusAPI {
     return new LifeplusAPIService().getWidgetData(bean);
   }
 
+  @Override
+  public Single<ContentsLogResultBean> setContentsLog(ContentsLogRequestBean bean) {
+    return new LifeplusAPIService().setContentsLog(bean);
+  }
+
   @Override
   public Single<EventListResultBean> getEventList(RequestBean bean) {
     return new LifeplusAPIService().getEventList(bean);

+ 84 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/view/screen/contents/ContentsModel.java

@@ -1,10 +1,13 @@
 package kr.co.zumo.app.lifeplus.view.screen.contents;
 
+import android.support.annotation.Nullable;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import io.reactivex.disposables.Disposable;
+import kr.co.zumo.app.lifeplus.bean.api.APIContentsLogModule;
 import kr.co.zumo.app.lifeplus.bean.api.APIData;
 import kr.co.zumo.app.lifeplus.bean.api.BookmarkBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsBookmarkRequestBean;
@@ -12,6 +15,8 @@ import kr.co.zumo.app.lifeplus.bean.api.ContentsDetailListBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsDetailResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsItemBean;
 import kr.co.zumo.app.lifeplus.bean.api.ContentsLikeRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogRequestBean;
+import kr.co.zumo.app.lifeplus.bean.api.ContentsLogResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ItemNoRequestBean;
 import kr.co.zumo.app.lifeplus.bean.api.LifeplusAPIBean;
 import kr.co.zumo.app.lifeplus.bean.api.SeriesItemBean;
@@ -23,6 +28,7 @@ import kr.co.zumo.app.lifeplus.supervisor.ContentsFlagHelper;
 import kr.co.zumo.app.lifeplus.tool.ReviewCounter;
 import kr.co.zumo.app.lifeplus.util.StringUtil;
 import kr.co.zumo.app.lifeplus.view.Event;
+import kr.co.zumo.app.lifeplus.view.IEventListener;
 import kr.co.zumo.app.lifeplus.view.dialog.ShareDialog;
 import kr.co.zumo.app.lifeplus.view.screen.my.bookmark.BookmarkModelHelper;
 import kr.co.zumo.app.lifeplus.view.screen.setting.SettingModelHelper;
@@ -42,6 +48,7 @@ public class ContentsModel extends ContentsBaseModel {
   private Disposable disposableDetail;
   private Disposable disposableSeriesLiked;
   private Disposable disposableSeriesBookmarked;
+  private Disposable disposableLog;
   private ContentsDetailListBean contentsDetailListBean;
   private SeriesItemBean selectedSeriesItemBean;
 
@@ -114,9 +121,13 @@ public class ContentsModel extends ContentsBaseModel {
     return getItem(getItemIndex());
   }
 
+  @Nullable
   protected ContentsItemBean getItem(int index) {
     if (null != getFirstItem()) {
       List<ContentsItemBean> list = contentsDetailListBean.getItemDetailList();
+      if (index >= list.size()) {
+        return null;
+      }
       return list.get(index);
     }
     return ContentsItemBean.toBean(contentsBean);
@@ -370,4 +381,77 @@ public class ContentsModel extends ContentsBaseModel {
   public String getMemberSpecialCode() {
     return SettingModelHelper.getInstance().getSpecialCode();
   }
+
+  /**
+   * 페이지 본 것으로 로그 추가
+   *
+   * @param currentIndex
+   */
+  public void log(int currentIndex) {
+    if (isLogFlushed) {
+      return;
+    }
+    ContentsItemBean bean = getItem(currentIndex);
+    if (null != bean) {
+      String pageNo = bean.getListItemNo();
+      pageNos.add(pageNo);
+    }
+  }
+
+  private List<String> pageNos;
+  private boolean isLogFlushed;
+
+  /**
+   * 로깅 초기화
+   */
+  public void initLog() {
+    isLogFlushed = false;
+    pageNos = new ArrayList<>();
+  }
+
+  /**
+   * 로그 전송
+   *
+   * @param listener
+   */
+  public void flushLog(IEventListener listener) {
+    if (isLogFlushed) {
+      // 1회만 로깅하기. 성공으로 리턴.
+      listener.onEvent(new Event.Builder(Event.SUCCESS).build());
+      return;
+    }
+    // log 된 페이지 no 를 순서대로 정렬
+    List<String> logNos = new ArrayList<>();
+
+    List<ContentsItemBean> list = getContentsDetailListBean().getItemDetailList();
+    if (null != list) {
+      int len = list.size();
+      for (int i = 0; i < len; ++i) {
+        String listItemNo = list.get(i).getListItemNo();
+        for (String pageNo : pageNos) {
+          if (pageNo.equals(listItemNo)) {
+            logNos.add(listItemNo);
+            break;
+          }
+        }
+      }
+    }
+
+    ContentsLogRequestBean requestBean = new ContentsLogRequestBean(getContentsNo());
+    requestBean.setItemNoBeans(logNos);
+
+    isLogFlushed = true;
+    disposableLog = new APIContentsLogModule().call(requestBean, new APIModuleListener<ContentsLogResultBean>(waiterCaller) {
+      @Override
+      public void onApiSuccess(ContentsLogResultBean resultBean) {
+        listener.onEvent(new Event.Builder(Event.SUCCESS).build());
+      }
+
+      @Override
+      public void onApiError(String errorMessage, APIError error) {
+        listener.onEvent(new Event.Builder(Event.ERROR).build());
+
+      }
+    });
+  }
 }

+ 61 - 28
app/src/main/java/kr/co/zumo/app/lifeplus/view/screen/contents/ContentsPresenter.java

@@ -24,6 +24,7 @@ import kr.co.zumo.app.lifeplus.tool.GuestContentsShowCounter;
 import kr.co.zumo.app.lifeplus.util.StringUtil;
 import kr.co.zumo.app.lifeplus.view.DoubleChecker;
 import kr.co.zumo.app.lifeplus.view.Event;
+import kr.co.zumo.app.lifeplus.view.IEventListener;
 import kr.co.zumo.app.lifeplus.view.command.WebCommand;
 import kr.co.zumo.app.lifeplus.view.dialog.ConfirmDialog;
 import kr.co.zumo.app.lifeplus.view.dialog.DialogBuilder;
@@ -112,10 +113,16 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
       String listType = contentsItemBean.getListType();
       view.draw(model.getContentsNo(), listType, model.getContentsDetailListBean());
 
+      // 로그 초기화
+      model.initLog();
+
       if (model.getCurrentPageIndex() > 0) {
+        // 특정 페이지에서 시작
         view.setScrollToPosition(model.getCurrentPageIndex());
       }
       else {
+        // 커버에서 시작
+        model.log(0); // 커버 로그 추가
         showWaiter(); // 커버 이지미 로딩 완료 전까지 표시
         view.setLiked(model.isItemLiked(), false);
         view.setBookmarked(model.isItemBookmarked(), false);
@@ -206,7 +213,9 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
   @Override
   protected boolean onBackPressedInternal() {
     if (false == view.dispatchBackPressed()) {
-      back();
+      flushLogAndContinue(event -> {
+        back();
+      });
     }
     return true;
   }
@@ -218,14 +227,17 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
         showMoreInfoPopup(event.getIndex());
         break;
       case Event.CLICK:
-        model.setSeriesSelectedIndex(event.getIndex());
-
-        // Series 는 itemNo 가 Series 를 가리키고 seriesItemNo 가 contents 의 itemNo 이므로
-        // 그대로 contentsView 에 전달하면 공유 등 문제가 있다.
-        // 이를 clone()하여 새로운 bean 으로 전달한다.
-        LifeplusContentsBean bean = model.getSelectedSeriesItemBean().clone();
-        model.setDeliveryPackaging(new ContentsDeliveryBean.Builder(bean).build());
-        go(ScreenID.CONTENTS);
+        // 시리즈 클릭
+        flushLogAndContinue(e -> {
+          model.setSeriesSelectedIndex(event.getIndex());
+
+          // Series 는 itemNo 가 Series 를 가리키고 seriesItemNo 가 contents 의 itemNo 이므로
+          // 그대로 contentsView 에 전달하면 공유 등 문제가 있다.
+          // 이를 clone()하여 새로운 bean 으로 전달한다.
+          LifeplusContentsBean bean = model.getSelectedSeriesItemBean().clone();
+          model.setDeliveryPackaging(new ContentsDeliveryBean.Builder(bean).build());
+          go(ScreenID.CONTENTS);
+        });
         break;
       case Event.LIKE:
         // series like
@@ -257,38 +269,47 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
         break;
       case Event.CLICK_HTML:
         // html 의 자바스크립트를 통해서 전달된 데이터
-        HtmlBean htmlBean = event.fromJson(HtmlBean.class);
-        if (htmlBean.getType() == HtmlBean.TYPE_APP) {
-          shipToWeb(htmlBean.getUrl(), ScreenID.WEB_FROM_CONTENTS);
-          go(ScreenID.WEB_FROM_CONTENTS);
-        }
-        else if (htmlBean.getType() == HtmlBean.TYPE_LINK) {
-          onCommand(new WebCommand(htmlBean.getUrl()));
-        }
+        flushLogAndContinue(e -> {
+          HtmlBean htmlBean = event.fromJson(HtmlBean.class);
+          if (htmlBean.getType() == HtmlBean.TYPE_APP) {
+            shipToWeb(htmlBean.getUrl(), ScreenID.WEB_FROM_CONTENTS);
+            go(ScreenID.WEB_FROM_CONTENTS);
+          }
+          else if (htmlBean.getType() == HtmlBean.TYPE_LINK) {
+            onCommand(new WebCommand(htmlBean.getUrl()));
+          }
+        });
         break;
       case Event.NEXT:
         view.setSmoothScrollToPosition(1);
         break;
       case Event.RECT:
-        Log.e("APP#  ContentsPresenter | onEventInternal", "|" + event.getString());
-        shipToWeb(event.getString(), ScreenID.WEB_FROM_CONTENTS);
-        go(ScreenID.WEB_FROM_CONTENTS);
+        // 클릭 영역
+        flushLogAndContinue(e -> {
+          Log.e("APP#  ContentsPresenter | onEventInternal", "|" + event.getString());
+          shipToWeb(event.getString(), ScreenID.WEB_FROM_CONTENTS);
+          go(ScreenID.WEB_FROM_CONTENTS);
+        });
         break;
       case Event.POINT:
-        // todo tool tip 표시 필요
-        Log.e("APP#  ContentsPresenter | onEventInternal", "|" + event.getString());
-        shipToWeb(event.getString(), ScreenID.WEB_PURCHASE);
-        go(ScreenID.WEB_PURCHASE);
+        flushLogAndContinue(e -> {
+          // todo tool tip 표시 필요
+          Log.e("APP#  ContentsPresenter | onEventInternal", "|" + event.getString());
+          shipToWeb(event.getString(), ScreenID.WEB_PURCHASE);
+          go(ScreenID.WEB_PURCHASE);
+        });
         break;
       case Event.OVER_VIEW:
         model.setDeliveryPackaging(new ContentsOverviewDeliveryBean(model.getContentsBean(), model.getContentsDetailListBean()));
         go(ScreenID.OVER_VIEW);
         break;
       case Event.WITH_SHOWN:
-        // 함께 본 컨텐츠
-        WithShownItemBean withShownItemBean = model.getContentsDetailListBean().getWithItemList().get(event.getIndex());
-        model.setDeliveryPackaging(new ContentsDeliveryBean.Builder(withShownItemBean).build());
-        go(ScreenID.CONTENTS);
+        flushLogAndContinue(e -> {
+          // 함께 본 컨텐츠
+          WithShownItemBean withShownItemBean = model.getContentsDetailListBean().getWithItemList().get(event.getIndex());
+          model.setDeliveryPackaging(new ContentsDeliveryBean.Builder(withShownItemBean).build());
+          go(ScreenID.CONTENTS);
+        });
         break;
       case Event.COVER:
         // 커버 로딩 완료
@@ -299,6 +320,10 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
     }
   }
 
+  private void flushLogAndContinue(IEventListener listener) {
+    model.flushLog(listener);
+  }
+
   @Override
   public void onScreenReady() {
 
@@ -397,6 +422,7 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
   public void onChangedPageIndex(int currentIndex) {
     model.setCurrentPageIndex(currentIndex);
 
+    model.log(currentIndex);
     Log.w("APP# ContentsPresenter | onChangedPageIndex", "|" + " currentIndex: " + currentIndex);
 
     /**
@@ -590,4 +616,11 @@ public class ContentsPresenter extends ContentsBasePresenter<ContentsModel, ICon
       })
       .show();
   }
+
+  @Override
+  public void onNavigationClickHome(NavigationBar navigationBar) {
+    flushLogAndContinue(event -> {
+      super.onNavigationClickHome(navigationBar);
+    });
+  }
 }