Project

General

Profile

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

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

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;
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
      }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

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

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

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

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

    
224
      getWindowWidth(conf);
225
      mGrid.updateGrid(this,mScreenWidth);
226
      }
227

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

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

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

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

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

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

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

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

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

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

    
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284

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

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

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

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

    
307
      RubikObjectList.savePreferences(editor);
308

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

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

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

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

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

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

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

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

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

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361
// PUBLIC API
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

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

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

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

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

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

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

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

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

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

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

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

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411

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

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

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

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
    public void switchToPlay(RubikObject object, int ordinal, int scrambles, int level)
431
      {
432
      Intent intent = new Intent(this, PlayActivity.class);
433
      intent.putExtra("level", level);
434
      intent.putExtra("name", object.getUpperName());
435
      intent.putExtra("scrambles", scrambles);
436
      intent.putExtra("local", object.isLocal() );
437
      intent.putExtra("ordinal", ordinal );
438
      startActivity(intent);
439
      }
440

    
441
///////////////////////////////////////////////////////////////////////////////////////////////////
442

    
443
    public void onScores(View v)
444
      {
445
      Bundle sBundle = new Bundle();
446
      sBundle.putString("argument", "false");
447
      RubikDialogScores scores = new RubikDialogScores();
448
      scores.setArguments(sBundle);
449
      scores.show(getSupportFragmentManager(), null);
450
      }
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
    public void onUpdates(View v)
455
      {
456
      RubikDialogUpdates diag = new RubikDialogUpdates();
457
      diag.show( getSupportFragmentManager(), RubikDialogUpdates.getDialogTag() );
458
      }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

    
462
    public void onExit(View v)
463
      {
464
      RubikDialogExit diag = new RubikDialogExit();
465
      diag.show(getSupportFragmentManager(), null);
466
      }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
    public void onAbout(View v)
471
      {
472
      RubikDialogAbout diag = new RubikDialogAbout();
473
      diag.show(getSupportFragmentManager(), null);
474
      }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

    
478
    public void onBandage(View v)
479
      {
480
      RubikDialogCreators diag = new RubikDialogCreators();
481
      diag.show(getSupportFragmentManager(), RubikDialogCreators.getDialogTag() );
482
      }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
    public void receiveUpdate(RubikUpdates updates)
487
      {
488
      int num = updates.getCompletedNumber();
489
      updateBubble(num);
490
      }
491

    
492
///////////////////////////////////////////////////////////////////////////////////////////////////
493

    
494
    public void objectDownloaded(String shortName)
495
      {
496
      mNumUpdates--;
497
      updateBubble(mNumUpdates);
498
      mGrid.updateGrid(this,mScreenWidth);
499
      }
500

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

    
503
    public int getType()
504
      {
505
      return 0;
506
      }
507

    
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509

    
510
    public void errorUpdate()
511
      {
512
      android.util.Log.e("D", "NewRubikActivity: Error receiving downloaded objects update");
513
      }
514
}
(1-1/3)