/*
* This file is part of Domodroid.
*
* Domodroid is Copyright (C) 2011 Pierre LAINE, Maxime CHOFARDET
*
* Domodroid is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* Domodroid is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Domodroid. If not, see <http://www.gnu.org/licenses/>.
*/
package activities;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
import android.preference.PreferenceManager;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.FrameLayout.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import org.domogik.domodroid13.R;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;
import Abstract.common_method;
import Abstract.load_parameters;
import Dialog.Dialog_House;
import Dialog.Dialog_Splash;
import Dialog.Dialog_Synchronize;
import Entity.Entity_Area;
import Entity.Entity_Room;
import database.Cache_management;
import database.WidgetUpdate;
import misc.changelog;
import misc.tracerengine;
import mq.Main;
import widgets.Basic_Graphical_zone;
@SuppressWarnings({"static-access"})
public class Activity_Main extends AppCompatActivity implements OnClickListener, NavigationView.OnNavigationItemSelectedListener {
private final String mytag = this.getClass().getName();
public static Context context;
private SharedPreferences SP_params;
private SharedPreferences.Editor SP_prefEditor;
private AlertDialog.Builder AD_notSyncAlert;
private AlertDialog.Builder AD_wifi_prefered;
private Widgets_Manager WM_Agent;
private Dialog_Synchronize DIALOG_dialog_sync;
private WidgetUpdate WU_widgetUpdate;
private Handler sbanim;
private static Handler widgetHandler;
private Intent INTENT_map = null;
private ImageView appname;
private ViewGroup VG_parent;
public static ScrollView SV_Main_ScrollView;
private Vector<String[]> history;
private int historyPosition;
private LinearLayout LL_house_map;
private LinearLayout LL_area;
private LinearLayout LL_room;
private LinearLayout LL_activ;
private Basic_Graphical_zone house;
private Basic_Graphical_zone map;
private Boolean reload = false;
private DialogInterface.OnDismissListener sync_listener = null;
private DialogInterface.OnDismissListener house_listener = null;
private static Boolean by_usage = false;
private Boolean init_done = false;
private final File backupprefs = new File(Environment.getExternalStorageDirectory() + "/domodroid/.conf/settings");
private final Thread waiting_thread = null;
private Activity_Main myself = null;
private tracerengine Tracer = null;
private ProgressDialog PG_dialog_message;
private Boolean end_of_init_requested = true;
private Entity_Room[] listRoom;
private Entity_Area[] listArea;
private Menu mainMenu;
private Toolbar toolbar;
private NavigationView mDrawer;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle drawerToggle;
private int mSelectedId;
public static ArrayList<HashMap<String, String>> listItem;
private ListView listePlace;
private SimpleAdapter adapter_map;
private PendingIntent pendingIntent_for_metrics;
private Intent intent_for_metrics;
private AlarmManager processTimer_for_metrics;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().getBooleanExtra("Exit me", false)) {
finish();
return; // add this to prevent from doing unnecessary stuffs
}
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception ignored) {
}
Activity_Main.context = getApplicationContext();
myself = this;
if (android.os.Build.VERSION.SDK_INT == 8) // FROYO (8)
{
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
}
SP_params = PreferenceManager.getDefaultSharedPreferences(this);
SP_prefEditor = SP_params.edit();
Tracer = tracerengine.getInstance(SP_params, this);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); // this sets the button visible
getSupportActionBar().setHomeButtonEnabled(true); // makes it clickable
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);// set your own icon
}
//Register metrics
if (SP_params.getBoolean("domodroid_metrics", true)) {
int repeatTime = 30; //Repeat alarm time in seconds
processTimer_for_metrics = (AlarmManager) getSystemService(ALARM_SERVICE);
intent_for_metrics = new Intent(this, metrics.MetricsServiceReceiver.class);
pendingIntent_for_metrics = PendingIntent.getBroadcast(this, 0, intent_for_metrics, PendingIntent.FLAG_UPDATE_CURRENT);
//get metrics every 30s
processTimer_for_metrics.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), repeatTime * 1000, pendingIntent_for_metrics);
}
initView();
drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_arrow_back_white);// set your own icon
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);// set your own icon
drawerToggle.syncState();
}
};
mDrawerLayout.setDrawerListener(drawerToggle);
//load default pref
//Added by Doume
try {
File storage = new File(Environment.getExternalStorageDirectory() + "/domodroid/.conf/");
if (!storage.exists()) {
boolean sucess = storage.mkdirs();
if (sucess == false)
Tracer.i(mytag, "No dir .conf created");
}
} catch (Exception e) {
Tracer.e(mytag, "creating dir /.conf/ error " + e.toString());
}
//Configure Tracer tool initial state
try {
File logpath = new File(Environment.getExternalStorageDirectory() + "/domodroid/.log/");
if (!logpath.exists()) {
boolean sucess = logpath.mkdirs();
if (sucess == false)
Tracer.i(mytag, "No dir .log created");
}
} catch (Exception e) {
Tracer.e(mytag, "creating dir /.log/ error " + e.toString());
}
//load_preferences(); //moved to abstract
load_parameters.load_preferences(SP_params, SP_prefEditor);
Tracer.set_profile(SP_params);
// Create .nomedia file, that will prevent Android image gallery from showing domodroid file
File nomedia = new File(Environment.getExternalStorageDirectory() + "/domodroid/.nomedia");
try {
if (!(nomedia.exists())) {
new FileOutputStream(nomedia).close();
boolean sucess = nomedia.createNewFile();
if (sucess == false)
Tracer.i(mytag, "No File .nomedia created");
}
} catch (Exception e) {
Tracer.e(mytag, "creating file .nomedia error " + e.toString());
}
appname = (ImageView) findViewById(R.id.app_name);
//todo try to solve history problems like in:
/*
STACK_TRACE=java.lang.NullPointerException: Attempt to invoke virtual method 'void java.util.Vector.add(int, java.lang.Object)' on a null object reference
at activities.Activity_Main.onOptionsItemSelected(Activity_Main.java:1096)
at android.app.Activity.onMenuItemSelected(Activity.java:3008)
at android.support.v4.b.l.onMenuItemSelected(FragmentActivity.java:403)
at android.support.v7.a.f.onMenuItemSelected(AppCompatActivity.java:189)
*/
history = new Vector<>();
LoadSelections();
// Prepare a listener to know when the house organization dialog is closed...
if (house_listener == null) {
house_listener = new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
//Redraw after house dialog closed.
refresh();
}
};
}
// Prepare a listener to know when a sync dialog is closed...
if (sync_listener == null) {
sync_listener = new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
Tracer.i(mytag, "sync dialog has been closed !");
// Is it success or fail ?
if (((Dialog_Synchronize) dialog).need_refresh) {
/*
//todo #141 ask user if it's is prefered wifi SSID.
ConnectivityManager connectivityManager
= (ConnectivityManager) (context.getSystemService(Context.CONNECTIVITY_SERVICE));
NetworkInfo[] netInfo = connectivityManager.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI"))
if (ni.isConnected()) {
WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
WifiInfo wifiInfo;
wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID().replace("\"", "");
SP_prefEditor.putString("prefered_wifi_ssid",ssid);
SP_prefEditor.commit();
}
}*/
// Sync has been successful : Force to refresh current main view
// Store settings to SDcard
common_method.save_params_to_file(Tracer, SP_prefEditor, mytag, getApplicationContext());
Tracer.i(mytag, "sync dialog requires a refresh !");
reload = true; // Sync being done, consider shared prefs are OK
VG_parent.removeAllViews();
if (WU_widgetUpdate == null) {
Tracer.i(mytag, "OnCreate WidgetUpdate is null startCacheengine!");
startCacheEngine(); //if sync dialog is closed
}
Bundle b = new Bundle();
//Notify sync complete to parent Dialog
b.putInt("id", 0);
b.putString("type", "root");
Message msg = new Message();
msg.setData(b);
if (widgetHandler != null)
widgetHandler.sendMessage(msg); // That should force to refresh Views
/* */
if (WU_widgetUpdate != null) {
WU_widgetUpdate.Disconnect(0); //That should disconnect all opened widgets from cache engine
//widgetUpdate.dump_cache(); //For debug
//dont_kill = true; // to avoid engines kill when onDestroy()
}
onResume();
} else {
Tracer.v(mytag, "sync dialog end with no refresh !");
}
((Dialog_Synchronize) dialog).need_refresh = false;
}
};
}
//update thread
sbanim = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
appname.setImageDrawable(getResources().getDrawable(R.drawable.app_name2));
getSupportActionBar().setLogo(R.drawable.app_name2);
} else if (msg.what == 1) {
appname.setImageDrawable(getResources().getDrawable(R.drawable.app_name3));
getSupportActionBar().setLogo(R.drawable.app_name3);
} else if (msg.what == 2) {
appname.setImageDrawable(getResources().getDrawable(R.drawable.app_name1));
getSupportActionBar().setLogo(R.drawable.app_name1);
} else if (msg.what == 3) {
appname.setImageDrawable(getResources().getDrawable(R.drawable.app_name4));
getSupportActionBar().setLogo(R.drawable.app_name4);
} else if (msg.what == 8000) {
Tracer.d(mytag, "Request to display message : 8000");
/*
if(dialog_message == null) {
Create_message_box();
}
dialog_message.setMessage("Starting cache engine...");
dialog_message.show();
*/
} else if (msg.what == 8001) {
AlertDialog.Builder dialog_stats_error = new AlertDialog.Builder(Activity_Main.this);
dialog_stats_error.setTitle(R.string.domogik_error);
dialog_stats_error.setMessage(R.string.stats_error);
dialog_stats_error.show();
} else if (msg.what == 8002) {
AlertDialog.Builder dialog_stats_error = new AlertDialog.Builder(Activity_Main.this);
dialog_stats_error.setTitle(R.string.domogik_error);
dialog_stats_error.setMessage("ERROR");
dialog_stats_error.show();
} else if (msg.what == 8999) {
//Cache engine is ready for use....
if (Tracer != null)
Tracer.i(mytag, "Cache engine has notified it's ready !");
//cache_ready=true;
if (end_of_init_requested)
end_of_init();
PG_dialog_message.dismiss();
//refresh view when initial cache ready #33
refresh();
}
}
};
//window manager to keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//Mains global scroll view
SV_Main_ScrollView = (ScrollView) findViewById(R.id.Main_ScrollView);
//Parent view
VG_parent = (ViewGroup) findViewById(R.id.home_container);
LL_house_map = new LinearLayout(this);
LL_house_map.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
LL_house_map.setOrientation(LinearLayout.HORIZONTAL);
LL_house_map.setPadding(5, 5, 5, 5);
LL_area = new LinearLayout(this);
LL_area.setOrientation(LinearLayout.VERTICAL);
LL_room = new LinearLayout(this);
LL_room.setOrientation(LinearLayout.VERTICAL);
LL_activ = new LinearLayout(this);
LL_activ.setOrientation(LinearLayout.VERTICAL);
house = new Basic_Graphical_zone(Tracer, getApplicationContext(), 0,
Graphics_Manager.Names_Agent(this, "House"),
"",
"house",
0, "", null);
house.setPadding(0, 0, 5, 0);
map = new Basic_Graphical_zone(Tracer, getApplicationContext(), 0,
Graphics_Manager.Names_Agent(this, "Map"),
"",
"map",
0, "", null);
map.setPadding(5, 0, 0, 0);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
house.setLayoutParams(param);
house.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (SP_params.getBoolean("SYNC", false)) {
loadWigets(0, "root");
historyPosition++;
try {
history.add(historyPosition, new String[]{"0", "root"});
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
Tracer.e("mytag", "ArrayIndexOutOfBoundsException when adding history navigation");
//Todo solved this bug:
/*
STACK_TRACE=java.lang.ArrayIndexOutOfBoundsException: length=0; index=2
at java.util.Vector.arrayIndexOutOfBoundsException(Vector.java:907)
at java.util.Vector.insertElementAt(Vector.java:590)
at java.util.Vector.add(Vector.java:140)
at activities.Activity_Main$8.onClick(Activity_Main.java:396)
at android.view.View.performClick(View.java:5207)
at android.view.View$PerformClick.run(View.java:21177)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5441)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
*/
}
} else {
if (AD_notSyncAlert == null)
createAlert();
AD_notSyncAlert.show();
}
}
});
map.setLayoutParams(param);
map.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (SP_params.getBoolean("SYNC", false)) {
//dont_freeze=true; //To avoid WidgetUpdate engine freeze
Tracer.w(mytag, "Before call to Map, Disconnect widgets from engine !");
if (WU_widgetUpdate != null) {
WU_widgetUpdate.Disconnect(0); //That should disconnect all opened widgets from cache engine
//widgetUpdate.dump_cache(); //For debug
//dont_kill = true; // to avoid engines kill when onDestroy()
}
INTENT_map = new Intent(Activity_Main.this, Activity_Map.class);
Tracer.i(mytag, "Call to Map, run it now !");
Tracer.Map_as_main = false;
startActivity(INTENT_map);
} else {
if (AD_notSyncAlert == null)
createAlert();
AD_notSyncAlert.show();
}
}
});
LL_house_map.addView(house);
LL_house_map.addView(map);
init_done = false;
// Detect if it's the 1st use after installation...
if (!SP_params.getBoolean("SPLASH", false)) {
// Yes, 1st use !
init_done = false;
reload = false;
if (backupprefs.exists()) {
// A backup exists : Ask if reload it
Tracer.i(mytag, "settings backup found after a fresh install...");
DialogInterface.OnClickListener reload_listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Tracer.d(mytag, "Reload dialog returns : " + which);
if (which == dialog.BUTTON_POSITIVE) {
reload = true;
} else if (which == dialog.BUTTON_NEGATIVE) {
reload = false;
}
check_answer();
dialog.dismiss();
}
};
AlertDialog.Builder dialog_reload = new AlertDialog.Builder(this);
dialog_reload.setTitle(getText(R.string.reload_title));
dialog_reload.setMessage(getText(R.string.home_reload));
dialog_reload.setPositiveButton(getText(R.string.reloadOK), reload_listener);
dialog_reload.setNegativeButton(getText(R.string.reloadNO), reload_listener);
//todo #94
dialog_reload.show();
init_done = false; //A choice is pending : Rest of init has to be completed...
} else {
//No settings backup found
Tracer.i(mytag, "no settings backup found after fresh install...");
end_of_init_requested = true;
// open server config view
Intent helpI = new Intent(Activity_Main.this, Preference.class);
//todo #94
//startActivity(helpI);
}
} else {
// It's not the 1st use after fresh install
// This method will be followed by 'onResume()'
end_of_init_requested = true;
}
if (SP_params.getBoolean("SYNC", false)) {
//A config exists and a sync as been done by past.
if (WU_widgetUpdate == null) {
Tracer.i(mytag, "OnCreate Params splash is false and WidgetUpdate is null startCacheengine!");
startCacheEngine();//if sync is done on create
}
}
// Changelog view
changelog changelog = new changelog(this);
if (changelog.firstRun())
try {
changelog.getLogDialog().show();
} catch (Exception e) {
Tracer.e(mytag, e.toString());
}
Tracer.v(mytag, "OnCreate() complete !");
// End of onCreate (UIThread)
}
@Override
public void onResume() {
super.onResume();
//get metrics every 30s
if (SP_params.getBoolean("domodroid_metrics", true)) {
int repeatTime = 30; //Repeat alarm time in seconds
AlarmManager processTimer = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, metrics.MetricsServiceReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
processTimer.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), repeatTime * 1000, pendingIntent);
}
Tracer.v(mytag + ".onResume", "Check if initialize requested !");
if (!init_done) {
Tracer.v(mytag + ".onResume", "Init not done!");
if (SP_params.getBoolean("SPLASH", false)) {
Tracer.v(mytag + ".onResume", "params Splash is false !");
//cache_ready = false;
//try to solve 1rst launch and orientation problem
Tracer.v(mytag + ".onresume", "Init not done! and params Splash is false startCacheengine!");
//startCacheEngine();
//end_of_init(); //Will be done when cache will be ready
}
} else {
Tracer.v(mytag + ".onResume", "Init done!");
end_of_init_requested = true;
if (WU_widgetUpdate != null) {
Tracer.v(mytag + ".onResume", "Widget update is not null so wakeup widget engine!");
WU_widgetUpdate.wakeup(); //If cache ready, that'll execute end_of_init()
}
}
if (end_of_init_requested)
refresh();
}
@Override
public void onPause() {
super.onPause();
Tracer.v(mytag + ".onPause", "Going to background !");
if (WU_widgetUpdate != null) {
if (!Tracer.Map_as_main) {
// We're the main initial activity
WU_widgetUpdate.set_sleeping(); //Don't cancel the cache engine : only freeze it
}
}
//Stop metrics.
if (SP_params.getBoolean("domodroid_metrics", true)) {
processTimer_for_metrics.cancel(pendingIntent_for_metrics);
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerToggle.syncState();
}
@Override
public void onDestroy() {
super.onDestroy();
this.WM_Agent = null;
widgetHandler = null;
if (SP_params.getFloat("API_VERSION", 0) >= 0.9f) {
SharedPreferences.Editor prefEditor = SP_params.edit();
JSONArray cached_dump = null;
if (WU_widgetUpdate != null) {
Tracer.d("#124", "dump cache");
try {
cached_dump = WU_widgetUpdate.dump_cache_to_json();
// save last value to sharedparams to load them later
prefEditor.putString("sensor_saved_value", cached_dump.toString());
Tracer.d("#124", cached_dump.toString());
Tracer.d("#124", "dump cached");
// save current time stamp to know when the pass was exit.
long currentTimestamp = (System.currentTimeMillis() / 1000);
Tracer.d("#124", "sensor_saved_timestamp" + currentTimestamp);
prefEditor.putString("sensor_saved_timestamp", String.valueOf(currentTimestamp));
} catch (JSONException e) {
Tracer.e("#124", "sensor_saved at exit error");
e.printStackTrace();
}
}
prefEditor.commit();
}
//Stop metrics.
if (SP_params.getBoolean("domodroid_metrics", true)) {
processTimer_for_metrics.cancel(pendingIntent_for_metrics);
}
if (WU_widgetUpdate != null) {
WU_widgetUpdate.Disconnect(0); //remove all pending subscribings
if (!Tracer.Map_as_main) {
// We're the main initial activity
Tracer.v(mytag + ".onDestroy", "cache engine set to sleeping !");
//PM_WakeLock.release(); // We allow screen shut, now...
WU_widgetUpdate.set_sleeping(); //Don't cancel the cache engine : only freeze it
// only if we are the main initial activity
}
}
/*
if(Tracer != null) {
Tracer.close(); //To flush text file, eventually
Tracer = null;
}
*/
}
private void Create_message_box() {
if (PG_dialog_message != null)
return;
PG_dialog_message = new ProgressDialog(this);
PG_dialog_message.setTitle(getText(R.string.please_wait));
PG_dialog_message.setMessage(getText(R.string.init_in_process));
//dialog_reload.setPositiveButton("OK", message_listener);
}
/*
public void force_DB_update() {
if(WU_widgetUpdate != null) {
WU_widgetUpdate.refreshNow();
}
}
*/
private void createAlert() {
AD_notSyncAlert = new AlertDialog.Builder(this);
AD_notSyncAlert.setTitle(getText(R.string.warning));
AD_notSyncAlert.setMessage(getText(R.string.not_sync));
AD_notSyncAlert.setNeutralButton(getText(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}
);
}
private void end_of_init() {
// Finalize screen appearances
if (Tracer == null)
Tracer = Tracer.getInstance(this);
Tracer.v(mytag, "end_of_init Main Screen..");
if (!reload) {
//alertDialog not sync splash
if (AD_notSyncAlert == null)
createAlert();
}
//splash
if (!SP_params.getBoolean("SPLASH", false)) {
Dialog_Splash dialog_splash = new Dialog_Splash(this);
dialog_splash.show();
SP_prefEditor.clear();
SP_prefEditor.putBoolean("SPLASH", true);
SP_prefEditor.commit();
return;
}
end_of_init_requested = false;
if (history != null)
Tracer.d(mytag, "OnactivityResult end of init history=" + history.toString() + " historyposition=" + historyPosition);
if (!init_done) {
history = null; //Free resource
history = new Vector<>();
}
//load widgets
if (widgetHandler == null) {
Tracer.v(mytag, "Starting WidgetHandler thread !");
widgetHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//#107 around here
Tracer.d("debug map bak #107", msg.getData().toString() + " history= " + history.toString() + " hystoryposition= " + historyPosition);
try {
if (msg.getData().getBoolean("refresh")) {
refresh();
} else if (!msg.getData().getBoolean("refresh")) {
historyPosition++;
loadWigets(msg.getData().getInt("id"), msg.getData().getString("type"));
//redraw the scrollview at the top position of the screen
SV_Main_ScrollView.post(new Runnable() {
@Override
public void run() {
SV_Main_ScrollView.scrollTo(0, 0);
}
});
Tracer.v(mytag + ".widgetHandler", "add history " + msg.getData().getInt("id") + " " + msg.getData().getString("type"));
history.add(historyPosition, new String[]{msg.getData().getInt("id") + "", msg.getData().getString("type")});
}
} catch (Exception e) {
Tracer.e(mytag + ".widgetHandler", "handler error into loadWidgets");
Tracer.e("debug map bak", e.toString());
}
}
};
}
if (WM_Agent == null) {
Tracer.v(mytag, "Starting wAgent !");
WM_Agent = new Widgets_Manager(Tracer, widgetHandler);
WM_Agent.widgetupdate = WU_widgetUpdate;
}
/*
if(T_starting != null) {
T_starting.cancel();
T_starting.setText("Creating widgets....");
T_starting.setDuration(Toast.LENGTH_SHORT);
T_starting.show();
}
*/
//dont_kill = false; //By default, the onDestroy activity will also kill engines
listePlace = (ListView) findViewById(R.id.listplace);
try {
listItem = new ArrayList<>();
adapter_map = new SimpleAdapter(getBaseContext(), listItem,
R.layout.item_in_listview_navigation_drawer, new String[]{"name", "icon"}, new int[]{R.id.name, R.id.icon});
listePlace.setAdapter(adapter_map);
listePlace.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
HashMap<String, String> map = listItem.get(position);
if (map.get("type").equals("action")) {
if (map.get("name").equals(context.getApplicationContext().getResources().getString(R.string.action_back))) {
Tracer.v(mytag, "clic move back in navigation drawer");
if (historyPosition != 0) {
historyPosition--;
}
refresh();
}
} else {
//redraw the scrollview at the top position of the screen
SV_Main_ScrollView.post(new Runnable() {
@Override
public void run() {
SV_Main_ScrollView.scrollTo(0, 0);
}
});
loadWigets(Integer.parseInt(map.get("id")), map.get("type"));
historyPosition++;
try {
history.add(historyPosition, new String[]{map.get("id"), map.get("type")});
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
Tracer.e("mytag", "ArrayIndexOutOfBoundsException when adding history navigation");
//Todo solved this bug:
}
if (map.get("type").equals("room")) {
//close navigationdrawer if select a room
mDrawerLayout.closeDrawer(GravityCompat.START);
}
}
}
});
listePlace.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Tracer.d(mytag, " On Longclick Place selected at Position = " + position);
HashMap<String, String> map = listItem.get(position);
if (map.get("type").equals("action")) {
Tracer.d(mytag, "long clic on action button");
return false;
} else {
Tracer.d(mytag, "On click Place selected at Position = " + map.toString());
//Todo delete this place directly from navigation drawer
return false;
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
if ((SP_params.getBoolean("START_ON_MAP", false) && (!Tracer.force_Main))) {
//#125 wait cache ready
//Solve #2029
if (SP_params.getBoolean("SYNC", false)) {
Tracer.v(mytag, "Direct start on Map requested...");
Tracer.Map_as_main = true; //Memorize that Map is now the main screen
INTENT_map = new Intent(Activity_Main.this, Activity_Map.class);
startActivity(INTENT_map);
} else {
if (AD_notSyncAlert == null)
createAlert();
AD_notSyncAlert.show();
}
} else {
Tracer.force_Main = false; //Reset flag 'called from Map view'
if (SP_params.getBoolean("SYNC", false)) {
if (!init_done) {
historyPosition = 0;
try {
history.add(historyPosition, new String[]{"0", "root"});
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
Tracer.e("mytag", "ArrayIndexOutOfBoundsException when adding history navigation");
//Todo solved this bug:
}
refresh();
}
} else {
if (AD_notSyncAlert == null)
createAlert();
AD_notSyncAlert.show();
}
}
init_done = true;
}
/*
* Check the answer after the proposal to reload existing settings (fresh install)
*/
private void check_answer() {
Tracer.v(mytag, "reload choice done..");
if (reload) {
// If answer is 'yes', load preferences from backup
Tracer.v(mytag, "reload settings..");
//loadSharedPreferencesFromFile(backupprefs); //moved to Abstract
if (load_parameters.loadSharedPreferencesFromFile(backupprefs, SP_prefEditor, Tracer)) {
LoadSelections(); // to set panel with known values
}
run_sync_dialog(); //after reload prefs at start
} else {
Tracer.v(mytag, "Settings not reloaded : clear database..");
File database = new File(Environment.getExternalStorageDirectory() + "/domodroid/.conf/domodroid.db");
try {
if (database.exists()) {
boolean sucess = database.delete();
if (sucess == false)
Tracer.i(mytag, "Database not deleted");
}
} catch (Exception e) {
Tracer.e(mytag, "deleting domodroid.db error " + e.toString());
}
// open server config view
Intent helpI = new Intent(Activity_Main.this, Preference.class);
startActivity(helpI);
}
if (!init_done) {
// Complete the UI init
end_of_init();
}
}
/*
private void loadSharedPreferencesFromFile(File src) {
ObjectInputStream input = null;
try {
input = new ObjectInputStream(new FileInputStream(src));
SP_prefEditor.clear();
Map<String, ?> entries = (Map<String, ?>) input.readObject();
for (Entry<String, ?> entry : entries.entrySet()) {
Object v = entry.getValue();
String key = entry.getKey();
Tracer.i(mytag, "Loading pref : " + key + " -> " + v.toString());
if (v instanceof Boolean)
SP_prefEditor.putBoolean(key, (Boolean) v);
else if (v instanceof Float)
SP_prefEditor.putFloat(key, (Float) v);
else if (v instanceof Integer)
SP_prefEditor.putInt(key, (Integer) v);
else if (v instanceof Long)
SP_prefEditor.putLong(key, (Long) v);
else if (v instanceof String)
SP_prefEditor.putString(key, (String) v);
}
SP_prefEditor.commit();
LoadSelections(); // to set panel with known values
} catch (IOException e) {
Tracer.e(mytag, "Can't load preferences file");
Tracer.e(mytag, e.toString());
} catch (ClassNotFoundException e) {
Tracer.e(mytag, "Can't load preferences file");
Tracer.e(mytag, e.toString());
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException ex) {
Tracer.e(mytag, "Can't load preferences file");
Tracer.e(mytag, ex.toString());
}
}
}
*/
private void loadWigets(int id, String type) {
Tracer.i(mytag + ".loadWidgets", "Construct main View id=" + id + " type=" + type);
VG_parent.removeAllViews();
LL_house_map.removeAllViews();
LL_house_map.addView(house);
LL_house_map.addView(map);
LL_area.removeAllViews();
LL_activ.removeAllViews();
LL_room.removeAllViews();
try {
int mytype = 0;
switch (type) {
case "root":
VG_parent.addView(LL_house_map); // House & map
if (!by_usage) {
// Version 0.2 or un-force by_usage : display house, map and areas
LL_area = WM_Agent.loadAreaWidgets(this, LL_area, SP_params);
VG_parent.addView(LL_area); //and areas
LL_activ = WM_Agent.loadActivWidgets(this, 1, "root", LL_activ, SP_params, mytype);//add widgets in root
} else {
// by_usage
//TODO #19 change 1 in loadRoomWidgets by the right value.
int load_area;
try {
load_area = Integer.valueOf(SP_params.getString("load_area_at_start", "1"));
} catch (Exception e) {
Tracer.e(mytag, e.toString());
load_area = 1;
}
//LL_room = WM_Agent.loadRoomWidgets(this, 1, LL_room, SP_params); //List of known usages 'as rooms'
LL_room = WM_Agent.loadRoomWidgets(this, load_area, LL_room, SP_params); //List of known usages 'as rooms'
VG_parent.addView(LL_room);
//LL_activ = WM_Agent.loadActivWidgets(this, 1, "area", LL_activ, SP_params, mytype);//add widgets in area 1
LL_activ = WM_Agent.loadActivWidgets(this, load_area, "area", LL_activ, SP_params, mytype);//add widgets in area 1
}
VG_parent.addView(LL_activ);
/*Should never arrive in this type.
}else if(type.equals("house")) {
//Only possible if Version 0.2 or un-force by_usage (the 'house' is never proposed to be clicked)
VG_parent.addView(LL_house_map); // House & map
LL_area = WM_Agent.loadAreaWidgets(this, LL_area, SP_params);
VG_parent.addView(LL_area); //and areas
LL_activ = WM_Agent.loadActivWidgets(this, id, type, LL_activ,SP_params, mytype);
VG_parent.addView(LL_activ);
*/
break;
case "statistics":
//Only possible if by_usage (the 'stats' is never proposed with Version 0.2 or un-force by_usage)
LL_activ = WM_Agent.loadActivWidgets(this, -1, type, LL_activ, SP_params, mytype);
VG_parent.addView(LL_activ);
break;
case "area":
//Only possible if Version 0.2 or un-force by_usage (the area 'usage' is never proposed to be clicked)
if (!by_usage) {
VG_parent.addView(LL_house_map); // House & map
}
LL_room = WM_Agent.loadRoomWidgets(this, id, LL_room, SP_params);//Add room in this area
VG_parent.addView(LL_room);
LL_activ = WM_Agent.loadActivWidgets(this, id, type, LL_activ, SP_params, mytype);//add widgets in this area
VG_parent.addView(LL_activ);
break;
case "room":
LL_activ = WM_Agent.loadActivWidgets(this, id, type, LL_activ, SP_params, mytype);//add widgets in this room
VG_parent.addView(LL_activ);
break;
}
update_navigation_menu();
Tracer.d(mytag, "List item= " + listItem.toString());
} catch (Exception e) {
Tracer.e(mytag, "Can't load area/room or widgets");
Tracer.e(mytag, e.toString());
}
}
private void LoadSelections() {
by_usage = SP_params.getBoolean("BY_USAGE", false);
}
private void run_sync_dialog() {
AD_wifi_prefered = new AlertDialog.Builder(this);
AD_wifi_prefered.setTitle(getText(R.string.sync_wifi_preferred_title));
AD_wifi_prefered.setMessage(getText(R.string.sync_wifi_preferred_message));
AD_wifi_prefered.setPositiveButton(getText(R.string.reloadOK), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
try {
WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
//replace and save "SSID" by SSID
SP_prefEditor.putString("prefered_wifi_ssid", ssid.substring(1, ssid.length()-1));
SP_prefEditor.commit();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, R.string.error_getting_wifi_ssid, Toast.LENGTH_LONG);
}
dialog.dismiss();
}
});
AD_wifi_prefered.setNegativeButton(getText(R.string.reloadNO), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AD_wifi_prefered.show();
//change sync parameter in case it fail.
SP_prefEditor.putBoolean("SYNC", false);
SP_prefEditor.commit();
if (!(WU_widgetUpdate == null)) {
WU_widgetUpdate.Disconnect(0); //Disconnect all widgets owned by Main
}
if (DIALOG_dialog_sync == null)
DIALOG_dialog_sync = new Dialog_Synchronize(Tracer, this, SP_params);
DIALOG_dialog_sync.reload = reload;
DIALOG_dialog_sync.setOnDismissListener(sync_listener);
DIALOG_dialog_sync.setParams(SP_params);
DIALOG_dialog_sync.show();
DIALOG_dialog_sync.startSync();
}
public void onClick(View v) {
//dont_freeze = false; // By default, onPause() will stop WidgetUpdate engine...
//ALL other that are not explicitly used
if (v.getTag().equals("reload_cancel")) {
Tracer.v(mytag, "Choosing no reload settings");
reload = false;
synchronized (waiting_thread) {
waiting_thread.notifyAll();
}
} else if (v.getTag().equals("reload_ok")) {
Tracer.v(mytag, "Choosing settings reload");
reload = true;
synchronized (waiting_thread) {
waiting_thread.notifyAll();
}
}
}
private void startCacheEngine() {
Cache_management.checkcache(Tracer, myself);
if (WU_widgetUpdate == null) {
this.Create_message_box();
PG_dialog_message.setMessage(getText(R.string.loading_cache));
PG_dialog_message.show();
Tracer.i(mytag, "Starting WidgetUpdate cache engine !");
WU_widgetUpdate = WidgetUpdate.getInstance();
WU_widgetUpdate.set_handler(sbanim, 0); //put our main handler into cache engine (as Main)
Boolean result = WU_widgetUpdate.init(Tracer, this, SP_params);
Tracer.i(mytag, "widgetupdate_wakup");
WU_widgetUpdate.wakeup();
if (!result)
return;
}
Tracer.set_engine(WU_widgetUpdate);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (SP_params.getBoolean("SYNC", false)) {
float api_version = SP_params.getFloat("API_VERSION", 0);
if (api_version < 0.7f) {
menu.findItem(R.id.menu_butler).setVisible(false);
}
}
menu.findItem(R.id.menu_exit).setVisible(!SP_params.getBoolean("START_ON_MAP", false));
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mainMenu = menu;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {
Tracer.d(mytag, "clic on drawertoggle");
return true;
}
//normal menu call.
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
case R.id.menu_butler:
if (SP_params.getBoolean("SYNC", false)) {
Intent intent = new Intent(this, Main.class);
this.startActivity(intent);
return true;
} else {
if (AD_notSyncAlert == null)
createAlert();
AD_notSyncAlert.show();
return true;
}
case R.id.menu_exit:
//Disconnect all opened sessions....
Tracer.v(mytag + "Exit", "Stopping WidgetUpdate thread !");
this.WM_Agent = null;
widgetHandler = null;
Tracer.set_engine(null);
if (!(WU_widgetUpdate == null)) {
WU_widgetUpdate.Disconnect(0); //Disconnect all widgets owned by Main
}
//dont_kill = false; //To force OnDestroy() to also kill engines
//And stop main program
finish();
/*todo uncomment this block to really quit the apps
//but it ctash in on destroy as some values are not initialize
Intent intent = new Intent(this, Activity_Main.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("Exit me", true);
startActivity(intent);
*/
return true;
case R.id.menu_house_config:
Tracer.v(mytag + ".onclick()", "Call to House settings screen");
Dialog_House DIALOG_house_set = new Dialog_House(Tracer, SP_params, myself);
DIALOG_house_set.show();
DIALOG_house_set.setOnDismissListener(house_listener);
return true;
case R.id.menu_preferences:
//Prepare a normal preferences activity.
Intent helpI = new Intent(Activity_Main.this, Preference.class);
startActivity(helpI);
return true;
case R.id.menu_about:
//dont_freeze=true; //To avoid WidgetUpdate engine freeze
Intent helpI1 = new Intent(Activity_Main.this, Activity_About.class);
startActivity(helpI1);
return true;
case R.id.menu_stats:
try {
if (SP_params.getBoolean("SYNC", false)) {
loadWigets(0, "statistics");
historyPosition++;
try {
history.add(historyPosition, new String[]{"0", "statistics"});
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
Tracer.e("mytag", "ArrayIndexOutOfBoundsException when adding history navigation");
//Todo solved this bug:
}
} else {
if (AD_notSyncAlert == null)
createAlert();
AD_notSyncAlert.show();
}
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
//todo find why java.lang.ArrayIndexOutOfBoundsException: 1 > 0
//Maybe when not sync or because of E/activities.Activity_Main(12801): Can not refresh this view
}
return true;
case R.id.menu_sync:
// click on 'sync' button into Sliding_Drawer View
run_sync_dialog(); // And run a resync with Rinor server
return true;
case R.id.menu_domogik_admin:
//launch a webview of domogik admin
Intent intent_webview = new Intent(context, webview_domogik_admin.class);
startActivity(intent_webview);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
//Physical button keycode 82 is menu button
//Physical button keycode 4 is back button
public boolean onKeyUp(int keyCode, KeyEvent event) {
Tracer.v(mytag, "onKeyUp keyCode = " + keyCode);
if ((keyCode == 82 || keyCode == 4) && mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
return false;
} else if ((keyCode == 4) && historyPosition > 0) {
if (history != null) {
Tracer.e("debug map bak", " history= " + history.toString() + " hystoryposition= " + historyPosition);
historyPosition--;
refresh();
return false;
} else {
Tracer.e(mytag, "history is null at this point");
}
} else if ((keyCode == 82) && mainMenu != null) {
mainMenu.performIdentifierAction(R.id.menu_overflow, 0);
}
return super.onKeyUp(keyCode, event);
}
@Override
public void onConfigurationChanged(Configuration newConfig)
//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
{
//Check if sync as been done by past to avoid crash
//on orientation change when user have to reload saved parameters.
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
if (SP_params.getBoolean("SYNC", false))
refresh();
}
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
mSelectedId = menuItem.getItemId();
itemSelection(mSelectedId);
return true;
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
//save selected item so it will remains same even after orientation change
outState.putInt("SELECTED_ID", mSelectedId);
}
private void initView() {
mDrawer = (NavigationView) findViewById(R.id.home_drawer);
mDrawer.setNavigationItemSelectedListener(this);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_home_layout);
}
private void itemSelection(int mSelectedId) {
Tracer.d(mytag, "Selected this item from navigation drawer: " + mSelectedId);
mDrawerLayout.closeDrawer(GravityCompat.START);
}
private void refresh() {
try {
loadWigets(Integer.parseInt(history.elementAt(historyPosition)[0]), history.elementAt(historyPosition)[1]);
} catch (Exception e) {
Tracer.e(mytag, "Can not refresh this view");
}
}
public void update_navigation_menu() {
adapter_map.notifyDataSetChanged();
listePlace.setAdapter(new SimpleAdapter(getBaseContext(), listItem,
R.layout.item_in_listview_navigation_drawer, new String[]{"name", "icon"}, new int[]{R.id.name, R.id.icon}));
Tracer.d(mytag, "Update navigation drawer listview");
}
/*
private void load_preferences() {
//Load default value to avoid crash.
String currlogpath = SP_params.getString("LOGNAME", "");
if (currlogpath.equals("")) {
//Not yet existing prefs : Configure debugging by default, to configure Tracer
currlogpath = Environment.getExternalStorageDirectory() + "/domodroid/.log/";
SP_prefEditor.putString("LOGPATH", currlogpath);
SP_prefEditor.putString("LOGNAME", "Domodroid.txt");
SP_prefEditor.putBoolean("SYSTEMLOG", false);
SP_prefEditor.putBoolean("TEXTLOG", false);
SP_prefEditor.putBoolean("SCREENLOG", false);
SP_prefEditor.putBoolean("LOGCHANGED", true);
SP_prefEditor.putBoolean("LOGAPPEND", false);
//set other default value
SP_prefEditor.putBoolean("twocol_lanscape", true);
SP_prefEditor.putBoolean("twocol_portrait", true);
} else {
SP_prefEditor.putBoolean("LOGCHANGED", true); //To force Tracer to consider current settings
}
//prefEditor.putBoolean("SYSTEMLOG", false); // For tests : no system logs....
SP_prefEditor.putBoolean("SYSTEMLOG", true); // For tests : with system logs....
SP_prefEditor.commit();
}
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Tracer.i(mytag, "OnactivityResult requestcode=" + requestCode + " resultcode=" + resultCode + " intent=" + data);
//because it will be follow by on resume() method
init_done = true;
}
}