blob: 9474cf6feef06c2f15499e5734bb2f45c2d33251 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2017 Orange.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* BAREAU Cyrille <cyrille.bareau@orange.com>,
* BONNARDEL Gregory <gbonnardel.ext@orange.com>,
* BOLLE Sebastien <sebastien.bolle@orange.com>.
*******************************************************************************/
package org.eclipse.om2m.android.dashboard;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.SortedSet;
import org.eclipse.om2m.android.dashboard.cse.OneM2MListener;
import org.eclipse.om2m.android.dashboard.cse.OneM2MRequest.OneM2MReqType;
import org.eclipse.om2m.android.dashboard.cse.OneM2MRequester;
import org.eclipse.om2m.android.dashboard.cse.models.OneM2MApplication;
import org.eclipse.om2m.android.dashboard.cse.models.SDTDevice;
import org.eclipse.om2m.android.dashboard.devices.DevicesActivity;
import org.eclipse.om2m.android.dashboard.main.MainAppEntryView;
import org.eclipse.om2m.android.dashboard.main.MainDevView;
import org.eclipse.om2m.android.dashboard.tools.OneM2MDeviceType;
import org.eclipse.om2m.android.dashboard.tools.SettingsManager;
import org.eclipse.om2m.android.dashboard.tools.Sorter;
import org.eclipse.om2m.android.dashboard.utils.OTBUtils;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
public class DashboardActivity extends CustomMainActivity
implements OnClickListener, OnLongClickListener, OneM2MListener {
private RelativeLayout rlDevs;
private GridLayout glApps;
private GridLayout glDevices;
private ImageView ivCSEState;
private ScrollView svDynamicCardScroller;
private TextView tvCounterApp;
private TextView tvCounterDev;
private TextView tvStatusTitle;
private List<SDTDevice> devices;
private SortedSet<OneM2MApplication> applications;
private boolean isInitialized = false;
private boolean cseDetected;
private boolean cseConnected;
private int width = 0;
private int appCol = -1;
private int devCol = -1;
// ================================================================================
Handler mDicoveryHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
boolean discovery_succeed = msg.getData().getBoolean("DISCOVERY_SUCCEED");
if (discovery_succeed) {
init();
} else {
reset();
}
}
};
// =====================================================================================
// Lifecycle
// =====================================================================================
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
// ||
// ||
// ||
// \/
@Override
protected void onStart() {
super.onStart();
}
// ||
// ||
// ||
// \/
@Override
protected void onResume() {
try {
super.onResume();
Log.i(getClass().getName(), "entering onResume");
isInitialized = false;
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
String language = SettingsManager.getInstance(this).getLanguage();
Resources res = getApplication().getResources();
Configuration config = res.getConfiguration();
config.locale = new Locale(language);
res.updateConfiguration(config, null);
try {
OneM2MDeviceType.initialize(res);
} catch (Exception e) {
Toast.makeText(this, "Error " + e, Toast.LENGTH_LONG).show();
}
setContentView(R.layout.main_activity);
rlDevs = (RelativeLayout)findViewById(R.id.rl_main_zone_devs);
tvCounterApp = (TextView)findViewById(R.id.tv_main_counter_app);
tvCounterDev = (TextView)findViewById(R.id.tv_main_counter_dev);
tvStatusTitle = (TextView)findViewById(R.id.tv_cse_status_title);
glApps = (GridLayout)findViewById(R.id.gl_main_cse_app);
glDevices = (GridLayout)findViewById(R.id.gl_main_cse_devices);
glApps.removeAllViews();
glDevices.removeAllViews();
ivCSEState = (ImageView)findViewById(R.id.iv_cse_state_icon);
svDynamicCardScroller = (ScrollView)findViewById(R.id.sv_main_dynamic_card_scroller);
ivCSEState.setOnLongClickListener(this);
refreshAll();
// add an observer to be sure that the layout is created before getting size
// and resize dynamically the card to take full screen size
tvStatusTitle.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//Remove it here unless you want to get this callback for EVERY
//layout pass, which can get you into infinite loops if you ever
//modify the layout from within this method.
tvStatusTitle.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// set dynamic card container size
int svHeight = svDynamicCardScroller.getMeasuredHeight();
int svWidth = svDynamicCardScroller.getMeasuredWidth();
int display_mode = getResources().getConfiguration().orientation;
if (display_mode == 1) { // portrait
LinearLayout llDynamicCardContainer = (LinearLayout)findViewById(R.id.ll_main_dynamic_card_container);
llDynamicCardContainer.setMinimumHeight(svHeight);
int appCol = svWidth / (165 + 70); // 165 = app view width
// 70 = margin between app
int devCol = svWidth / (150 + 70); // 150 = dev view width
// 70 = margin between dev
glApps.setColumnCount(appCol);
glDevices.setColumnCount(devCol);
}
else { // landscape
resize();
LinearLayout llLeftCardContainer = (LinearLayout)findViewById(R.id.ll_cse_left);
LayoutParams params = llLeftCardContainer.getLayoutParams();
double px = (double) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 175, llLeftCardContainer.getResources().getDisplayMetrics());
params.width = (width * 4) / 9; // Left (apps) weight = 5
// Right (devs) weight = 4
int cappCol = (int) Math.floor( ((double) width) * 4 / 9 / px); // 165 = app view width
// 70 = margin between app
appCol = cappCol;
devCol = ((width * 4) / 9) / (160 + 70); // 150 = dev view width
// 70 = margin between dev
try {
glApps.removeAllViews();
glApps.setColumnCount(appCol);
Log.d(getClass().getName(), "number of app col=" + appCol);
} catch(Exception e) {
// glApps.setColumnCount(appCol+1);
}
try {
glDevices.removeAllViews();
glDevices.setColumnCount(devCol);
Log.d(getClass().getName(), "number of devices col=" + devCol);
} catch(Exception e) {
// glDevices.setColumnCount(devCol+1);
}
}
// init data with last informations
refreshAll();
}
});
init();
Log.i(getClass().getName(), "leaving onResume");
} catch(Exception e) {
e.printStackTrace();
try {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
dialogBuilder.setTitle("Error " + e);
dialogBuilder.setMessage(e.getMessage());
dialogBuilder.setPositiveButton(R.string.dialog_btn_ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
}
});
dialogBuilder.create().show();
} catch (Exception e2) {
Toast.makeText(this, "Error " + e, Toast.LENGTH_LONG).show();
}
}
}
// ||
// ||
// ||
// \/
@Override
protected void onPause() {
super.onPause();
}
// ||
// ||
// ||
// \/
@Override
protected void onStop() {
super.onStop();
OneM2MRequester.getInstance().cancelMyPollingRequests();
}
// ||
// ||
// ||
// \/
@Override
protected void onDestroy() {
super.onDestroy();
}
// =====================================================================================
private void reset() {
refreshCSE(false, false);
if (devices != null) {
devices.clear();
}
glDevices.removeAllViews();
applications = null;
glApps.removeAllViews();
refreshAll();
}
private void init() {
if (! isInitialized) {
OneM2MRequester.getInstance().sendPollingRequest(OneM2MReqType.INCSE_STATUS, null,
getApplicationContext(), this, OneM2MRequester.DEFAULT_POLLING_DELAY);
OneM2MRequester.getInstance().sendPollingRequest(OneM2MReqType.DEVICES, null,
getApplicationContext(), this, OneM2MRequester.DEFAULT_POLLING_DELAY);
OneM2MRequester.getInstance().sendPollingRequest(OneM2MReqType.APPLICATIONS, null,
getApplicationContext(), this, OneM2MRequester.DEFAULT_POLLING_DELAY);
isInitialized = true;
}
}
private void refreshAll() {
Log.i(getClass().getName(), "entering refreshAll");
refreshCSE(cseDetected, cseConnected);
refreshDevices();
refreshApplications();
}
private synchronized void refreshCSE(boolean detected, boolean connected) {
Log.i(getClass().getName(), "entering refreshHab");
try {
if (! detected) {
ivCSEState.setImageDrawable(getResources().getDrawable(R.drawable.otb_picto_led_notconnected));
tvStatusTitle.setText(getResources().getString(R.string.main_cse_state_not_detected));
cseDetected = false;
cseConnected = false;
} else if (! connected) {
ivCSEState.setImageDrawable(getResources().getDrawable(R.drawable.otb_picto_led_notconnected));
tvStatusTitle.setText(getResources().getString(R.string.main_cse_state_not_connected));
cseDetected = true;
cseConnected = false;
} else {
ivCSEState.setImageDrawable(getResources().getDrawable(R.drawable.otb_picto_led_ok));
tvStatusTitle.setText(getResources().getString(R.string.main_cse_state_ok));
cseDetected = true;
cseConnected = true;
}
} catch (Exception e) {
}
}
private synchronized void refreshDevices() {
Log.i(getClass().getName(), "entering refreshDevices");
if (devices == null) {
if (tvCounterDev != null) {
tvCounterDev.setText("0");
}
glDevices.removeAllViews();
return;
}
int deviceCounter = 0;
// add/update devices
List<MainDevView> newViews = new ArrayList<MainDevView>();
for (SDTDevice sdtDevice : devices) {
deviceCounter += 1;
boolean deviceAlreadyKnown = false;
for (int i = 0; i < glDevices.getChildCount(); i++) {
Object obj = glDevices.getChildAt(i);
if (obj instanceof MainDevView) {
MainDevView devView = (MainDevView)obj;
if ((devView != null) && (sdtDevice.getRi().equals(devView.getSDTDevice().getRi()))) {
// same entry => refresh count
deviceAlreadyKnown = true;
devView.setData(sdtDevice);
break;
}
}
}
if (! deviceAlreadyKnown) {
// create a new device
MainDevView devView = new MainDevView(getApplicationContext(), null);
devView.setData(sdtDevice);
// add device
newViews.add(devView);
}
}
try {
glDevices.setColumnCount(devCol);
} catch(Exception e) {
}
for (MainDevView v : newViews)
glDevices.addView(v, 0);
// remove old devices
List<Integer> indexToRemove = new ArrayList<Integer>();
for (int i = 0; i < glDevices.getChildCount(); i++) {
Object obj = glDevices.getChildAt(i);
if (obj instanceof MainDevView) {
boolean deviceFound = false;
SDTDevice renderedDevice = ((MainDevView)obj).getSDTDevice();
if (devices.contains(renderedDevice)) {
deviceFound = true;
}
if (! deviceFound) {
indexToRemove.add(i);
}
}
}
for (Integer i : indexToRemove) {
try {
glDevices.removeViewAt(i);
}
catch(Exception e){}
}
if (tvCounterDev != null) {
tvCounterDev.setText("" + deviceCounter);
}
resize();
}
private synchronized void refreshApplications() {
Log.i(getClass().getName(), "entering refreshApplications");
if (OTBUtils.isEmpty(applications)) {
if (tvCounterApp != null) {
tvCounterApp.setText("0");
}
glApps.removeAllViews();
return;
}
if (tvCounterApp != null) {
tvCounterApp.setText("" + applications.size());
}
// add/update applications
int idx = 0;
for (OneM2MApplication app : applications) {
boolean found = false;
for (int i = 0; i < glApps.getChildCount(); i++) {
Object obj = glApps.getChildAt(i);
if (obj instanceof MainAppEntryView) {
MainAppEntryView appView = (MainAppEntryView)obj;
if ((appView != null) && appView.app.getRi().equals(app.getRi())) {
// same entry => refresh count
found = true;
appView.setData(app);
break;
}
}
}
if (! found) {
// create a new entry
MainAppEntryView appView =
new MainAppEntryView(getApplicationContext(), null);
appView.setData(app);
// add entry
glApps.addView(appView, idx);
}
idx += 1;
}
// remove old entries
List<View> indexToRemove = new ArrayList<View>();
for (int i = 0; i < glApps.getChildCount(); i++) {
Object obj = glApps.getChildAt(i);
if (obj instanceof MainAppEntryView) {
MainAppEntryView appEntryView = (MainAppEntryView)obj;
boolean found = false;
for (OneM2MApplication application : applications) {
if (appEntryView.app.getRi().equals(application.getRi())) {
found = true;
break;
}
}
if (! found) {
indexToRemove.add((View) obj);
}
}
}
for (View v : indexToRemove) {
glApps.removeView(v);
}
resize();
}
private void resize() {
// refresh container height
int display_mode = getResources().getConfiguration().orientation;
if (display_mode != 1) {
// landscape
int margin10dp = Math.round(10 *
(getApplicationContext().getResources().getDisplayMetrics().xdpi
/ DisplayMetrics.DENSITY_DEFAULT));
int svMainHeight = svDynamicCardScroller.getMeasuredHeight();
LinearLayout llRightCardContainer = (LinearLayout)findViewById(R.id.ll_cse_right);
RelativeLayout rlHabCardContainer = (RelativeLayout)findViewById(R.id.rl_main_zone_cse);
RelativeLayout rlAppsCardContainer = (RelativeLayout)findViewById(R.id.rl_main_zone_apps);
RelativeLayout rlDevsCardContainer = (RelativeLayout)findViewById(R.id.rl_main_zone_devs);
int svHabHeight = rlHabCardContainer.getMeasuredHeight();
int svAppHeight = rlAppsCardContainer.getMeasuredHeight();
int svDevHeight = (svHabHeight + svAppHeight);
int svHeight = 0, appMinHeight = 0, devMinHeight = 0;
svHeight = Math.max(svAppHeight + svHabHeight, svDevHeight /*+ svUsrHeight*/);
svHeight = Math.max(svHeight, svMainHeight);
appMinHeight = svHeight - svHabHeight - margin10dp;
devMinHeight = svHeight ;
rlAppsCardContainer.setMinimumHeight(appMinHeight);
rlDevsCardContainer.setMinimumHeight(devMinHeight);
rlAppsCardContainer.invalidate();
rlDevsCardContainer.invalidate();
}
}
// =====================================================================================
// User actions
// =====================================================================================
@Override
public void onClick(View v) {
if (v instanceof RelativeLayout) {
RelativeLayout layoutClicked = (RelativeLayout)v;
if (layoutClicked == rlDevs) {
startActivity(new Intent(DashboardActivity.this,
DevicesActivity.class));
}
}
}
@Override
public boolean onLongClick(View v) {
if (v instanceof ImageView) {
ImageView viewClicked = (ImageView)v;
if (viewClicked == ivCSEState) {
// OTBHabRequester.getInstance().sendRequest(OTBHabReqType.DEBUG,
// null, getApplicationContext(), this);
}
}
return false;
}
@SuppressWarnings("unchecked")
@Override
public void onOneM2MResponse(OneM2MReqType requestType, Object response) {
if (requestType == OneM2MReqType.APPLICATIONS) {
List<OneM2MApplication> apps = (List<OneM2MApplication>)response;
applications = Sorter.getSortedApplications(apps);
refreshApplications();
} else if (requestType == OneM2MReqType.DEVICES) {
devices = (List<SDTDevice>) response;
refreshDevices();
} else if (requestType == OneM2MReqType.INCSE_STATUS) {
boolean isConnected = (Boolean) response;
refreshCSE(isConnected, isConnected);
}
}
@Override
public void onOneM2MError(OneM2MReqType requestType, String msg) {
Toast.makeText(this, "Error " + msg, Toast.LENGTH_LONG).show();
}
}