Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / MainActivity.java @ c820515c

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, RubikDialogScores.ScoresInvoker
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, mScreenHeight;
70
    private TextView mBubbleUpdates;
71
    private int mNumUpdates;
72
    private int mCurrentObject;
73
    private MainScrollGrid mGrid;
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

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

    
85
      mCurrentObject = 0;
86
      mJustStarted = true;
87
      mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
88

    
89
      cutoutHack();
90
      computeHeights();
91

    
92
      mCurrVersion = getAppVers();
93

    
94
      mBubbleUpdates = findViewById(R.id.bubbleUpdates);
95
      mBubbleUpdates.setVisibility(View.INVISIBLE);
96
      mNumUpdates = 0;
97

    
98
      Thread thread = new Thread()
99
        {
100
        public void run()
101
          {
102
          RubikInAppMessanging listener = new RubikInAppMessanging();
103
          FirebaseInAppMessaging.getInstance().addClickListener(listener);
104
          }
105
        };
106

    
107
      thread.start();
108
      }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111
// this does not include possible insets
112

    
113
    private void computeHeights()
114
      {
115
      LinearLayout.LayoutParams pU = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
116
      LinearLayout layoutTop = findViewById(R.id.upperBar);
117
      layoutTop.setLayoutParams(pU);
118

    
119
      LinearLayout.LayoutParams pS = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1-2*RATIO_BAR);
120
      ScrollView scroll = findViewById(R.id.objectScroll);
121
      scroll.setLayoutParams(pS);
122

    
123
      LinearLayout.LayoutParams pL = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
124
      LinearLayout layoutBot = findViewById(R.id.lowerBar);
125
      layoutBot.setLayoutParams(pL);
126
      }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

    
130
    private void hideNavigationBar()
131
      {
132
      mCurrentApiVersion = Build.VERSION.SDK_INT;
133

    
134
      if(mCurrentApiVersion >= Build.VERSION_CODES.KITKAT)
135
        {
136
        final View decorView = getWindow().getDecorView();
137

    
138
        decorView.setSystemUiVisibility(FLAGS);
139

    
140
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener()
141
          {
142
          @Override
143
          public void onSystemUiVisibilityChange(int visibility)
144
            {
145
            if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0)
146
              {
147
              decorView.setSystemUiVisibility(FLAGS);
148
              }
149
            }
150
          });
151
        }
152
      }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
    @Override
157
    public void onAttachedToWindow()
158
      {
159
      super.onAttachedToWindow();
160

    
161
      getWindowWidth(getResources().getConfiguration());
162
      mGrid = new MainScrollGrid();
163
      mGrid.createGrid(this,mScreenWidth);
164

    
165
      if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P )
166
        {
167
        DisplayCutout cutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
168
        int insetHeight = cutout!=null ? cutout.getSafeInsetTop() : 0;
169

    
170
        if( insetHeight>0 )
171
          {
172
          LinearLayout.LayoutParams pH = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
173
          LinearLayout layoutHid = findViewById(R.id.hiddenBar);
174
          layoutHid.setLayoutParams(pH);
175

    
176
          LinearLayout.LayoutParams pS = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1-3*RATIO_BAR);
177
          ScrollView scroll = findViewById(R.id.objectScroll);
178
          scroll.setLayoutParams(pS);
179
          }
180
        }
181
      }
182

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184
// do not avoid cutouts
185

    
186
    private void cutoutHack()
187
      {
188
      if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P )
189
        {
190
        getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
191
        }
192
      }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
    private void getWindowWidth(Configuration conf)
197
      {
198
      int dpi = getResources().getDisplayMetrics().densityDpi;
199
      float conv = ((float) dpi/DisplayMetrics.DENSITY_DEFAULT);
200

    
201
      mScreenWidth = (int) (conf.screenWidthDp*conv + 0.5f);
202
      mScreenHeight= (int) (conf.screenHeightDp*conv + 0.5f);
203
      }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
    @Override
208
    public void onWindowFocusChanged(boolean hasFocus)
209
      {
210
      super.onWindowFocusChanged(hasFocus);
211

    
212
      if( mCurrentApiVersion >= Build.VERSION_CODES.KITKAT && hasFocus )
213
        {
214
        getWindow().getDecorView().setSystemUiVisibility(FLAGS);
215
        }
216
      }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
    @Override
221
    public void onConfigurationChanged(@NonNull Configuration conf)
222
      {
223
      super.onConfigurationChanged(conf);
224

    
225
      getWindowWidth(conf);
226
      if( mGrid!=null ) mGrid.updateGrid(this,mScreenWidth);
227
      }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
    
231
    @Override
232
    protected void onPause() 
233
      {
234
      super.onPause();
235
      RubikNetwork.onPause();
236
      savePreferences();
237
      }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
    
241
    @Override
242
    protected void onResume() 
243
      {
244
      super.onResume();
245

    
246
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
247
      restorePreferences(preferences,mJustStarted);
248

    
249
      RubikNetwork network = RubikNetwork.getInstance();
250
      network.signUpForUpdates(this);
251

    
252
      if( mJustStarted )
253
        {
254
        mJustStarted = false;
255

    
256
        network.downloadUpdates(this);
257
        RubikScores scores = RubikScores.getInstance();
258
        scores.incrementNumRuns();
259
        scores.setCountry(this);
260
        }
261

    
262
      if( !mOldVersion.equals(mCurrVersion) ) displayNovelties();
263
      }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
    private void displayNovelties()
268
      {
269
      Bundle bundle = new Bundle();
270
      bundle.putString("argument",mOldVersion);
271
      RubikDialogAbout newDialog = new RubikDialogAbout();
272
      newDialog.setArguments(bundle);
273
      newDialog.show(getSupportFragmentManager(), RubikDialogAbout.getDialogTag() );
274
      }
275

    
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277
    
278
    @Override
279
    protected void onDestroy() 
280
      {
281
      super.onDestroy();
282
      }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

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

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
    private void savePreferences()
302
      {
303
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
304
      SharedPreferences.Editor editor = preferences.edit();
305

    
306
      editor.putString("appVersion", mCurrVersion );
307

    
308
      RubikObjectList.savePreferences(editor);
309

    
310
      RubikScores scores = RubikScores.getInstance();
311
      scores.savePreferences(editor);
312

    
313
      boolean success = editor.commit();
314
      if( !success ) android.util.Log.e("D", "Failed to save preferences");
315
      }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318

    
319
    private void restorePreferences(SharedPreferences preferences, boolean justStarted)
320
      {
321
      mOldVersion = preferences.getString("appVersion","");
322

    
323
      RubikObjectList.restorePreferences(this,preferences,justStarted);
324
      RubikScores scores = RubikScores.getInstance();
325
      scores.restorePreferences(preferences);
326

    
327
      if( scores.isVerified() )
328
        {
329
        FirebaseAnalytics analytics = getAnalytics();
330
        analytics.setUserId(scores.getName());
331
        }
332
      }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

    
336
    private void updateBubble(int num)
337
      {
338
      runOnUiThread(new Runnable()
339
        {
340
        @Override
341
        public void run()
342
          {
343
          mNumUpdates = num;
344

    
345
          if( num>0 )
346
            {
347
            String shownNum = String.valueOf(num);
348
            mBubbleUpdates.setText(shownNum);
349
            mBubbleUpdates.setVisibility(View.VISIBLE);
350
            int height = (int)(0.05f*mScreenWidth);
351
            mBubbleUpdates.setTextSize(TypedValue.COMPLEX_UNIT_PX,height);
352
            }
353
          else
354
            {
355
            mBubbleUpdates.setVisibility(View.INVISIBLE);
356
            }
357
          }
358
        });
359
      }
360

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362
// PUBLIC API
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
    public FirebaseAnalytics getAnalytics()
366
      {
367
      return mFirebaseAnalytics;
368
      }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
    public int getObjectOrdinal()
373
      {
374
      return mCurrentObject;
375
      }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
    public void setCurrentObject(int current)
380
      {
381
      mCurrentObject = current;
382
      }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
    public void switchToTutorial(int objectOrdinal)
387
      {
388
      Intent intent = new Intent(this, TutorialActivity.class);
389
      intent.putExtra("obj", objectOrdinal);
390
      startActivity(intent);
391
      }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
    public void switchToConfig(int objectOrdinal)
396
      {
397
      Intent intent = new Intent(this, ConfigActivity.class);
398
      intent.putExtra("obj", objectOrdinal);
399
      startActivity(intent);
400
      }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
    public void switchToBandagedCreator(int objectOrdinal)
405
      {
406
      Intent intent = new Intent(this, BandagedActivity.class);
407
      intent.putExtra("obj", objectOrdinal);
408
      startActivity(intent);
409
      }
410

    
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

    
413
    public void switchToSolver(int objectOrdinal)
414
      {
415
      Intent intent = new Intent(this, SolverActivity.class);
416
      intent.putExtra("obj", objectOrdinal);
417
      startActivity(intent);
418
      }
419

    
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421

    
422
    public void switchToPattern(int objectOrdinal)
423
      {
424
      Intent intent = new Intent(this, PatternActivity.class);
425
      intent.putExtra("obj", objectOrdinal);
426
      startActivity(intent);
427
      }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
    public void switchToPlay(RubikObject object, int ordinal, int scrambles, int level)
432
      {
433
      boolean local = object.isLocal();
434
      String name = local ? object.getLowerName() : object.getUpperName();
435

    
436
      Intent intent = new Intent(this, PlayActivity.class);
437
      intent.putExtra("level", level);
438
      intent.putExtra("name", name );
439
      intent.putExtra("scrambles", scrambles);
440
      intent.putExtra("local", local );
441
      intent.putExtra("ordinal", ordinal );
442
      startActivity(intent);
443
      }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

    
447
    public void onScores(View v)
448
      {
449
      Bundle sBundle = new Bundle();
450
      sBundle.putString("argument", "false");
451
      RubikDialogScores scores = new RubikDialogScores();
452
      scores.setArguments(sBundle);
453
      scores.show(getSupportFragmentManager(), null);
454
      }
455

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

    
458
    public void onSettings(View v)
459
      {
460
      int sw = (int)(mScreenWidth*0.7);
461
      int sh = (int)(mScreenHeight*0.2f);
462

    
463
      int vw = v.getWidth();
464

    
465
      MainSettingsPopup popup = new MainSettingsPopup(this,mScreenWidth,mScreenHeight);
466
      popup.displayPopup(this,v,sw,sh,(int)((vw-sw)/2),0);
467
      }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
    public void onUpdates(View v)
472
      {
473
      RubikDialogUpdates diag = new RubikDialogUpdates();
474
      diag.show( getSupportFragmentManager(), RubikDialogUpdates.getDialogTag() );
475
      }
476

    
477
///////////////////////////////////////////////////////////////////////////////////////////////////
478

    
479
    public void onExit(View v)
480
      {
481
      RubikDialogExit diag = new RubikDialogExit();
482
      diag.show(getSupportFragmentManager(), null);
483
      }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

    
487
    public void onAbout(View v)
488
      {
489
      RubikDialogAbout diag = new RubikDialogAbout();
490
      diag.show(getSupportFragmentManager(), null);
491
      }
492

    
493
///////////////////////////////////////////////////////////////////////////////////////////////////
494

    
495
    public void onBandage(View v)
496
      {
497
      RubikDialogCreators diag = new RubikDialogCreators();
498
      diag.show(getSupportFragmentManager(), RubikDialogCreators.getDialogTag() );
499
      }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

    
503
    public void receiveUpdate(RubikUpdates updates)
504
      {
505
      int num = updates.getCompletedNumber();
506
      updateBubble(num);
507
      }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
    public void objectDownloaded(String shortName)
512
      {
513
      mNumUpdates--;
514
      updateBubble(mNumUpdates);
515
      mGrid.updateGrid(this,mScreenWidth);
516
      }
517

    
518
///////////////////////////////////////////////////////////////////////////////////////////////////
519

    
520
    public int getType()
521
      {
522
      return 0;
523
      }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
    public void errorUpdate()
528
      {
529
      android.util.Log.e("D", "NewRubikActivity: Error receiving downloaded objects update");
530
      }
531
}
(1-1/4)