Project

General

Profile

Download (16.6 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / main / MainActivity.java @ 7bb30586

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.main;
11

    
12
import android.content.Intent;
13
import android.content.SharedPreferences;
14
import android.content.pm.PackageInfo;
15
import android.content.pm.PackageManager;
16
import android.content.res.Configuration;
17
import android.os.Build;
18
import android.os.Bundle;
19
import android.util.DisplayMetrics;
20
import android.util.TypedValue;
21
import android.view.DisplayCutout;
22
import android.view.View;
23
import android.view.ViewGroup;
24
import android.view.WindowManager;
25
import android.widget.LinearLayout;
26
import android.widget.ScrollView;
27
import android.widget.TextView;
28

    
29
import androidx.annotation.NonNull;
30
import androidx.appcompat.app.AppCompatActivity;
31
import androidx.preference.PreferenceManager;
32

    
33
import com.google.firebase.analytics.FirebaseAnalytics;
34
import com.google.firebase.inappmessaging.FirebaseInAppMessaging;
35

    
36
import org.distorted.bandaged.BandagedActivity;
37
import org.distorted.config.ConfigActivity;
38
import org.distorted.dialogs.RubikDialogAbout;
39
import org.distorted.dialogs.RubikDialogCreators;
40
import org.distorted.dialogs.RubikDialogExit;
41
import org.distorted.dialogs.RubikDialogScores;
42
import org.distorted.dialogs.RubikDialogUpdates;
43
import org.distorted.external.RubikNetwork;
44
import org.distorted.external.RubikScores;
45
import org.distorted.external.RubikUpdates;
46
import org.distorted.messaging.RubikInAppMessanging;
47
import org.distorted.objects.RubikObject;
48
import org.distorted.objects.RubikObjectList;
49
import org.distorted.patternui.PatternActivity;
50
import org.distorted.playui.PlayActivity;
51
import org.distorted.solverui.SolverActivity;
52
import org.distorted.tutorials.TutorialActivity;
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
public class MainActivity extends AppCompatActivity implements RubikNetwork.Updatee
57
{
58
    public static final float RATIO_BAR = 0.080f;
59
    public static final int FLAGS =  View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
60
                                   | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
61
                                   | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
62
                                   | View.SYSTEM_UI_FLAG_FULLSCREEN
63
                                   | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
64

    
65
    private boolean mJustStarted;
66
    private FirebaseAnalytics mFirebaseAnalytics;
67
    private int mCurrentApiVersion;
68
    private String mOldVersion, mCurrVersion;
69
    private int mScreenWidth;
70
    private TextView mBubbleUpdates;
71
    private int mNumUpdates;
72
    private MainScrollGrid mGrid;
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
    @Override
77
    protected void onCreate(Bundle savedState)
78
      {
79
      super.onCreate(savedState);
80
      setTheme(R.style.MaterialThemeNoActionBar);
81
      setContentView(R.layout.main);
82
      hideNavigationBar();
83

    
84
      mJustStarted = true;
85
      mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
86

    
87
      cutoutHack();
88
      computeHeights();
89

    
90
      mCurrVersion = getAppVers();
91

    
92
      Thread thread = new Thread()
93
        {
94
        public void run()
95
          {
96
          RubikInAppMessanging listener = new RubikInAppMessanging();
97
          FirebaseInAppMessaging.getInstance().addClickListener(listener);
98
          }
99
        };
100

    
101
      thread.start();
102
      }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
// this does not include possible insets
106

    
107
    private void computeHeights()
108
      {
109
      LinearLayout.LayoutParams pU = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
110
      LinearLayout layoutTop = findViewById(R.id.upperBar);
111
      layoutTop.setLayoutParams(pU);
112

    
113
      LinearLayout.LayoutParams pS = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1-2*RATIO_BAR);
114
      ScrollView scroll = findViewById(R.id.objectScroll);
115
      scroll.setLayoutParams(pS);
116

    
117
      LinearLayout.LayoutParams pL = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
118
      LinearLayout layoutBot = findViewById(R.id.lowerBar);
119
      layoutBot.setLayoutParams(pL);
120
      }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
    private void hideNavigationBar()
125
      {
126
      mCurrentApiVersion = Build.VERSION.SDK_INT;
127

    
128
      if(mCurrentApiVersion >= Build.VERSION_CODES.KITKAT)
129
        {
130
        final View decorView = getWindow().getDecorView();
131

    
132
        decorView.setSystemUiVisibility(FLAGS);
133

    
134
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener()
135
          {
136
          @Override
137
          public void onSystemUiVisibilityChange(int visibility)
138
            {
139
            if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0)
140
              {
141
              decorView.setSystemUiVisibility(FLAGS);
142
              }
143
            }
144
          });
145
        }
146
      }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
    @Override
151
    public void onAttachedToWindow()
152
      {
153
      super.onAttachedToWindow();
154

    
155
      getWindowWidth(getResources().getConfiguration());
156
      mGrid = new MainScrollGrid();
157
      mGrid.createGrid(this,mScreenWidth);
158

    
159
      if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P )
160
        {
161
        DisplayCutout cutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
162
        int insetHeight = cutout!=null ? cutout.getSafeInsetTop() : 0;
163

    
164
        if( insetHeight>0 )
165
          {
166
          LinearLayout.LayoutParams pH = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
167
          LinearLayout layoutHid = findViewById(R.id.hiddenBar);
168
          layoutHid.setLayoutParams(pH);
169

    
170
          LinearLayout.LayoutParams pS = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1-3*RATIO_BAR);
171
          ScrollView scroll = findViewById(R.id.objectScroll);
172
          scroll.setLayoutParams(pS);
173
          }
174
        }
175
      }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178
// do not avoid cutouts
179

    
180
    private void cutoutHack()
181
      {
182
      if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P )
183
        {
184
        getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
185
        }
186
      }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
    private void getWindowWidth(Configuration conf)
191
      {
192
      int dpi = getResources().getDisplayMetrics().densityDpi;
193
      float conv = ((float) dpi/DisplayMetrics.DENSITY_DEFAULT);
194

    
195
      mScreenWidth = (int) (conf.screenWidthDp*conv + 0.5f);
196
      }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
    @Override
201
    public void onWindowFocusChanged(boolean hasFocus)
202
      {
203
      super.onWindowFocusChanged(hasFocus);
204

    
205
      if( mCurrentApiVersion >= Build.VERSION_CODES.KITKAT && hasFocus )
206
        {
207
        getWindow().getDecorView().setSystemUiVisibility(FLAGS);
208
        }
209
      }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
    @Override
214
    public void onConfigurationChanged(@NonNull Configuration conf)
215
      {
216
      super.onConfigurationChanged(conf);
217

    
218
      getWindowWidth(conf);
219
      mGrid.updateGrid(this,mScreenWidth);
220
      }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223
    
224
    @Override
225
    protected void onPause() 
226
      {
227
      super.onPause();
228
      RubikNetwork.onPause();
229
      savePreferences();
230
      }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233
    
234
    @Override
235
    protected void onResume() 
236
      {
237
      super.onResume();
238

    
239
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
240
      restorePreferences(preferences,mJustStarted);
241

    
242
      mBubbleUpdates = findViewById(R.id.bubbleUpdates);
243
      mBubbleUpdates.setVisibility(View.INVISIBLE);
244
      mNumUpdates = 0;
245

    
246
      RubikNetwork network = RubikNetwork.getInstance();
247
      network.signUpForUpdates(this);
248
      network.downloadUpdates(this);
249

    
250
      if( mJustStarted )
251
        {
252
        mJustStarted = false;
253
        RubikScores scores = RubikScores.getInstance();
254
        scores.incrementNumRuns();
255
        scores.setCountry(this);
256
        }
257

    
258
      if( !mOldVersion.equals(mCurrVersion) ) displayNovelties();
259
      }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

    
263
    private void displayNovelties()
264
      {
265
      Bundle bundle = new Bundle();
266
      bundle.putString("argument",mOldVersion);
267
      RubikDialogAbout newDialog = new RubikDialogAbout();
268
      newDialog.setArguments(bundle);
269
      newDialog.show(getSupportFragmentManager(), RubikDialogAbout.getDialogTag() );
270
      }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
    
274
    @Override
275
    protected void onDestroy() 
276
      {
277
      super.onDestroy();
278
      }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
    private String getAppVers()
283
      {
284
      try
285
        {
286
        PackageInfo pInfo = getPackageManager().getPackageInfo( getPackageName(), 0);
287
        return pInfo.versionName;
288
        }
289
      catch( PackageManager.NameNotFoundException e )
290
        {
291
        return "unknown";
292
        }
293
      }
294

    
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

    
297
    private void savePreferences()
298
      {
299
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
300
      SharedPreferences.Editor editor = preferences.edit();
301

    
302
      editor.putString("appVersion", mCurrVersion );
303

    
304
      RubikObjectList.savePreferences(editor);
305

    
306
      boolean success = editor.commit();
307
      if( !success ) android.util.Log.e("D", "Failed to save preferences");
308
      }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

    
312
    private void restorePreferences(SharedPreferences preferences, boolean justStarted)
313
      {
314
      mOldVersion = preferences.getString("appVersion","");
315

    
316
      RubikObjectList.restorePreferences(this,preferences,justStarted);
317
      RubikScores scores = RubikScores.getInstance();
318

    
319
      if( scores.isVerified() )
320
        {
321
        FirebaseAnalytics analytics = getAnalytics();
322
        analytics.setUserId(scores.getName());
323
        }
324
      }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
    private void updateBubble(int num)
329
      {
330
      runOnUiThread(new Runnable()
331
        {
332
        @Override
333
        public void run()
334
          {
335
          mNumUpdates = num;
336

    
337
          if( num>0 )
338
            {
339
            String shownNum = String.valueOf(num);
340
            mBubbleUpdates.setText(shownNum);
341
            mBubbleUpdates.setVisibility(View.VISIBLE);
342
            int height = (int)(0.05f*mScreenWidth);
343
            mBubbleUpdates.setTextSize(TypedValue.COMPLEX_UNIT_PX,height);
344
            }
345
          else
346
            {
347
            mBubbleUpdates.setVisibility(View.INVISIBLE);
348
            }
349
          }
350
        });
351
      }
352

    
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354
// PUBLIC API
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
    public FirebaseAnalytics getAnalytics()
358
      {
359
      return mFirebaseAnalytics;
360
      }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
    public void switchToTutorial(int objectOrdinal)
365
      {
366
      Intent intent = new Intent(this, TutorialActivity.class);
367
      intent.putExtra("obj", objectOrdinal);
368
      startActivity(intent);
369
      }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
    public void switchToConfig(int objectOrdinal)
374
      {
375
      Intent intent = new Intent(this, ConfigActivity.class);
376
      intent.putExtra("obj", objectOrdinal);
377
      startActivity(intent);
378
      }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
    public void switchToBandagedCreator(int objectOrdinal)
383
      {
384
      Intent intent = new Intent(this, BandagedActivity.class);
385
      intent.putExtra("obj", objectOrdinal);
386
      startActivity(intent);
387
      }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
    public void switchToSolver(int objectOrdinal)
392
      {
393
      Intent intent = new Intent(this, SolverActivity.class);
394
      intent.putExtra("obj", objectOrdinal);
395
      startActivity(intent);
396
      }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
    public void switchToPattern(int objectOrdinal)
401
      {
402
      Intent intent = new Intent(this, PatternActivity.class);
403
      intent.putExtra("obj", objectOrdinal);
404
      startActivity(intent);
405
      }
406

    
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

    
409
    public void switchToPlay(RubikObject object, int scrambles, boolean free, int level)
410
      {
411
      Intent intent = new Intent(this, PlayActivity.class);
412
      intent.putExtra("level", level);
413
      intent.putExtra("name", object.getUpperName());
414
      intent.putExtra("scrambles", scrambles);
415
      intent.putExtra("local", object.isLocal() );
416
      intent.putExtra("ordinal", object.getObjectOrdinal() );
417
      intent.putExtra("free", free );
418
      startActivity(intent);
419
      }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

    
423
    public void onScores(View v)
424
      {
425
      Bundle sBundle = new Bundle();
426
      sBundle.putString("argument", "false");
427
      RubikDialogScores scores = new RubikDialogScores();
428
      scores.setArguments(sBundle);
429
      scores.show(getSupportFragmentManager(), null);
430
      }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
    public void onUpdates(View v)
435
      {
436
      RubikDialogUpdates diag = new RubikDialogUpdates();
437
      diag.show( getSupportFragmentManager(), RubikDialogUpdates.getDialogTag() );
438
      }
439

    
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

    
442
    public void onExit(View v)
443
      {
444
      RubikDialogExit diag = new RubikDialogExit();
445
      diag.show(getSupportFragmentManager(), null);
446
      }
447

    
448
///////////////////////////////////////////////////////////////////////////////////////////////////
449

    
450
    public void onAbout(View v)
451
      {
452
      RubikDialogAbout diag = new RubikDialogAbout();
453
      diag.show(getSupportFragmentManager(), null);
454
      }
455

    
456
///////////////////////////////////////////////////////////////////////////////////////////////////
457

    
458
    public void onBandage(View v)
459
      {
460
      RubikDialogCreators diag = new RubikDialogCreators();
461
      diag.show(getSupportFragmentManager(), RubikDialogCreators.getDialogTag() );
462
      }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465

    
466
    public void receiveUpdate(RubikUpdates updates)
467
      {
468
      int num = updates.getCompletedNumber();
469
      updateBubble(num);
470
      }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473

    
474
    public void objectDownloaded(String shortName)
475
      {
476
      mNumUpdates--;
477
      updateBubble(mNumUpdates);
478
      mGrid.updateGrid(this,mScreenWidth);
479
      }
480

    
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

    
483
    public int getType()
484
      {
485
      return 0;
486
      }
487

    
488
///////////////////////////////////////////////////////////////////////////////////////////////////
489

    
490
    public void errorUpdate()
491
      {
492
      android.util.Log.e("D", "NewRubikActivity: Error receiving downloaded objects update");
493
      }
494
}
(1-1/3)