Crash Handler Klassen umbenannt
[DHBWCampusApp.git] / app / src / main / java / de / dhbwloe / campusapp / CampusApp.java
1 /* CampusApp.java
2  *
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 package de.dhbwloe.campusapp;
17
18 import android.content.Context;
19 import android.content.Intent;
20 import android.nfc.NfcAdapter;
21 import android.os.Bundle;
22 import android.support.v4.app.FragmentActivity;
23 import android.util.Log;
24 import android.view.KeyEvent;
25 import android.view.View;
26 import android.support.design.widget.NavigationView;
27 import android.support.v4.view.GravityCompat;
28 import android.support.v4.widget.DrawerLayout;
29 import android.support.v7.app.ActionBarDrawerToggle;
30 import android.support.v7.widget.Toolbar;
31 import android.view.Menu;
32 import android.view.MenuItem;
33 import android.view.inputmethod.EditorInfo;
34 import android.view.inputmethod.InputMethodManager;
35 import android.widget.EditText;
36 import android.widget.ImageView;
37 import android.widget.LinearLayout;
38 import android.widget.TextView;
39
40 import java.util.Date;
41
42 public class CampusApp extends FragmentActivity {
43     private boolean bSearchActive = false;
44     private CampusAppContext AppContext = null;
45
46     /*
47     * Dev Info:
48     *
49     * Die App besteht aus einer einzigen Activity, auf welcher dynamisch Fragmente platziert werden.
50     * Das Menü, sowie die Headerleiste befinden sich auf der Activity, sind dementsprechend immer verfügbar.
51     *
52     * Zur laufzeit der App wird eine einzige Instanz der Klasse CampusAppContext angelegt.
53     * Dieser Kontext dient als einstiegspunkt für sämmtliche global verfügbaren verwaltungs tools.
54     * Dazu gehören:
55     *   AppContext.getNavigationManager()    NavigationManager   Verwaltet die angezeigten Fragmente und deren Navigation
56     *                                                            .navigatePage("Dashboard")  to navigate to the Dashboard
57     *   ... to be continued ...
58      */
59
60     @Override
61     protected void onCreate(Bundle savedInstanceState) {
62         Log.i("CampusApp", "Event: onCreate");
63
64         if(CampusAppContext.DEBUG) {
65             final Thread.UncaughtExceptionHandler systemExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
66             final CampusAppCrashHandler oExceptionHandler = new CampusAppCrashHandler();
67             Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler() {
68                 @Override
69                 public void uncaughtException(Thread thread, Throwable e) {
70                     oExceptionHandler.handleUncaughtException(thread, e);
71                     //systemExceptionHandler.uncaughtException(thread, e);
72                     System.exit(1);
73                 }
74             });
75         }
76
77         super.onCreate(savedInstanceState);
78         setContentView(R.layout.activity_campus_app);
79
80         // Erstelle neuen AppContext, wenn keiner existiert
81         AppContext = CampusAppContext.getInstance();
82         if(AppContext == null)
83             AppContext = new CampusAppContext(this, R.id.fragment_container, R.id.nav_view);
84         else
85             AppContext.setMainActivity(this);
86
87         // Wenn die App aus dem Ruhezustand (oder auch Orientation change) reaktiviert wird soll nicht zuerst der Splashscreen angezeigt werden.
88         boolean instantRestore = false;
89         if(savedInstanceState != null) {
90             long lastrun = savedInstanceState.getLong("lastrun");
91             lastrun = ((new Date()).getTime()/1000) - lastrun;
92             Log.i("CampusApp", "Restored from Idle state! Idled: "+lastrun+" secs");
93             if(lastrun < 30) {
94                 instantRestore = true;
95
96                 // restore previous Title
97                 AppContext.setTitle(savedInstanceState.getString("activetitle"));
98             }
99
100
101             Bundle contextVars = savedInstanceState.getBundle("savedContextVariables");
102             if(contextVars != null) {
103                 Bundle contextVariables = AppContext.getContextVariables();
104                 contextVariables.putAll(contextVars);
105             }
106         }
107
108         prepareMainUi();
109         if(instantRestore) // orientation change
110             loadMainUi();
111         else
112             // don't add navigation to SlashScreen, or even from SplashScreen to Dashboard to the history log!
113             // it would be very strange to return to the SplashScreen or an "empty" page on return ;)
114             AppContext.getNavigationManager().navigatePage("SplashScreen", null, false);
115
116     }
117
118     @Override
119     public void onSaveInstanceState(Bundle savedInstanceState) {
120         Log.i("CampusApp", "Event: onSaveInstanceState");
121
122         // Save instance state during "restarts" due to orientation changes.
123         // We don't want to see the splash screen everytime the orientation changes ;)
124         savedInstanceState.putLong("lastrun", (new Date()).getTime() / 1000);
125         savedInstanceState.putString("activepage", AppContext.getNavigationManager().getCurrentPageName());
126         TextView titleView = (TextView) findViewById(R.id.title);
127         savedInstanceState.putString("activetitle", titleView.getText().toString());
128
129         Bundle contextVariables = AppContext.getContextVariables();
130         savedInstanceState.putBundle("savedContextVariables", contextVariables);
131
132         // Always call the superclass so it can save the view hierarchy state
133         super.onSaveInstanceState(savedInstanceState);
134     }
135
136     public void prepareMainUi() {
137         ImageView btnOpenSearch = (ImageView) findViewById(R.id.search_button);
138         btnOpenSearch.setVisibility(View.GONE);
139     }
140
141     public void loadMainUi() {
142         ImageView btnOpenSearch = (ImageView) findViewById(R.id.search_button);
143
144         btnOpenSearch.setVisibility(View.VISIBLE);
145         setupActionBar();
146         setupSearchTriggers();
147
148         AppContext.getNfcCardListener().startNfcListener();
149     }
150
151     private void setupActionBar() {
152         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
153         DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
154         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
155         drawer.setDrawerListener(toggle);
156         toggle.syncState();
157
158         NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
159         navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
160             @SuppressWarnings("StatementWithEmptyBody")
161             @Override
162             public boolean onNavigationItemSelected(MenuItem item) {
163                 // Handle navigation view item clicks here.
164                 int id = item.getItemId();
165
166                 for(CampusAppContext.NavigationItem navitem : AppContext.NAVIGATION_TARGETS) {
167                     if(navitem.navItemId == id) {
168                         AppContext.getNavigationManager().navigatePage(navitem.navTarget);
169                         break;
170                     }
171                 }
172
173                 DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
174                 drawer.closeDrawer(GravityCompat.START);
175                 return true;
176             }
177         });
178     }
179
180     private void setupSearchTriggers() {
181         ImageView btnOpenSearch = (ImageView) findViewById(R.id.search_button);
182         ImageView btnCloseSearch = (ImageView) findViewById(R.id.search_clear);
183         EditText edtSearchInput = (EditText) findViewById(R.id.search_input);
184         TextView txtTitle = (TextView) findViewById(R.id.title);
185
186         // EventListener für Suchfunktion
187         btnOpenSearch.setOnClickListener(new View.OnClickListener() {
188             @Override
189             public void onClick(View view) {
190                 triggerSearchPanel(true);
191             }
192         });
193         edtSearchInput.setOnFocusChangeListener(new View.OnFocusChangeListener() {
194             @Override
195             public void onFocusChange(View v, boolean hasFocus) {
196                 EditText edtSearchInput = (EditText) v;
197                 if (!hasFocus && edtSearchInput.getText().length() == 0) {
198                     triggerSearchPanel(false);
199                 }
200             }
201         });
202         edtSearchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
203             @Override
204             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
205                 if (actionId == EditorInfo.IME_ACTION_SEARCH) {
206                     EditText edtSearchInput = (EditText) v;
207                     triggerSearchAction(edtSearchInput.getText().toString());
208                     triggerSearchPanel(false);
209                     return true;
210                 }
211                 return false;
212             }
213         });
214         btnCloseSearch.setOnClickListener(new View.OnClickListener() {
215             @Override
216             public void onClick(View view) {
217                 EditText edtSearchInput = (EditText) findViewById(R.id.search_input);
218                 edtSearchInput.setText("");
219                 triggerSearchPanel(false);
220             }
221         });
222         txtTitle.setOnClickListener(new View.OnClickListener() {
223             @Override
224             public void onClick(View view) {
225                 triggerSearchPanel(true);
226             }
227         });
228
229     }
230
231     private void triggerSearchPanel(boolean show) {
232         if(bSearchActive == show)
233             return;
234         bSearchActive = show;
235         LinearLayout layTitleContainer = (LinearLayout) findViewById(R.id.title_container);
236         LinearLayout laySearchContainer = (LinearLayout) findViewById(R.id.search_container);
237         EditText edtSearchInput = (EditText) findViewById(R.id.search_input);
238
239         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
240         if(show) {
241             layTitleContainer.setVisibility(View.GONE);
242             laySearchContainer.setVisibility(View.VISIBLE);
243             edtSearchInput.requestFocus();
244
245             imm.showSoftInput(edtSearchInput, InputMethodManager.SHOW_IMPLICIT);
246         } else {
247             layTitleContainer.setVisibility(View.VISIBLE);
248             laySearchContainer.setVisibility(View.GONE);
249
250             View view = this.getCurrentFocus();
251             if (view != null) {
252                 imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
253             }
254         }
255     }
256
257     private void triggerSearchAction(String query) {
258         Bundle bundle = new Bundle();
259         bundle.putString("query", query);
260
261         AppContext.getNavigationManager().navigatePage("AppSearch", bundle);
262     }
263
264     @Override
265     public void onBackPressed() {
266         DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
267         if (drawer.isDrawerOpen(GravityCompat.START)) {
268             drawer.closeDrawer(GravityCompat.START);
269         } else if(!AppContext.getNavigationManager().back()) {
270             super.onBackPressed(); // trigger system action if internal navigation manager returns false for back()
271         }
272     }
273
274     @Override
275     public boolean onCreateOptionsMenu(Menu menu) {
276         // Inflate the menu; this adds items to the action bar if it is present.
277         getMenuInflater().inflate(R.menu.campus_app, menu);
278         return true;
279     }
280
281     @Override
282     public boolean onOptionsItemSelected(MenuItem item) {
283         // Handle action bar item clicks here. The action bar will
284         // automatically handle clicks on the Home/Up button, so long
285         // as you specify a parent activity in AndroidManifest.xml.
286         int id = item.getItemId();
287
288         //noinspection SimplifiableIfStatement
289         if (id == R.id.action_settings) {
290             return true;
291         }
292
293         return super.onOptionsItemSelected(item);
294     }
295
296     /* nfc listener related callbacks */
297     @Override
298     public void onResume() {
299         if(AppContext == null)
300             AppContext = CampusAppContext.getInstance();
301         if(AppContext == null)
302             AppContext = new CampusAppContext(this, R.id.fragment_container, R.id.nav_view);
303         else
304             AppContext.setMainActivity(this);
305
306         super.onResume();
307         Log.i("CampusApp", "onResume event");
308         AppContext.getNfcCardListener().resumeForefrontDispatcher();
309     }
310
311     @Override
312     public void onPause() {
313         super.onPause();
314         Log.i("CampusApp", "Event: onPause");
315         AppContext.getNfcCardListener().pauseForefrontDispatcher();
316     }
317
318     @Override
319     public void onNewIntent(Intent intent) {
320         if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
321             AppContext.getNfcCardListener().handleNfcEvent(intent);
322         }
323     }
324
325 }