Skip to content

Commit 28d4ae7

Browse files
committed
Implementation of new permissions management pt. 2
1 parent 2d644a1 commit 28d4ae7

16 files changed

Lines changed: 151 additions & 61 deletions

File tree

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
android:theme="@style/Theme.Speech"/>
102102

103103
<service android:name="nie.translator.rtranslator.voice_translation._conversation_mode._conversation.ConversationService"
104-
android:foregroundServiceType="microphone"/>
104+
android:foregroundServiceType="dataSync|microphone"/>
105105
<service android:name="nie.translator.rtranslator.voice_translation._walkie_talkie_mode._walkie_talkie.WalkieTalkieService"
106106
android:foregroundServiceType="dataSync|microphone"/>
107107
<service android:name="nie.translator.rtranslator.GeneralService" />

app/src/main/java/nie/translator/rtranslator/GeneralActivity.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,37 @@
1919
import android.content.DialogInterface;
2020
import android.content.Intent;
2121
import android.net.Uri;
22+
import android.os.Bundle;
23+
2224
import androidx.appcompat.app.AlertDialog;
2325
import androidx.fragment.app.FragmentActivity;
2426

2527
import javax.annotation.Nullable;
2628

29+
import nie.translator.rtranslator.access.AccessActivity;
30+
2731

2832
public abstract class GeneralActivity extends FragmentActivity {
2933

34+
@Override
35+
protected void onCreate(@androidx.annotation.Nullable Bundle savedInstanceState) {
36+
super.onCreate(savedInstanceState);
37+
// if the models are not loaded and an activity different than LoadingActivity or AccessActivity is created,
38+
// that means that the system has killed the app, and now it is launching the app with the last activity (restoring it).
39+
// In this case we start the loading activity instead, otherwise the app will crash for the lack of loaded models.
40+
// After the loading of the models, the app will handle itself the restore of the latest opened fragment (using the "fragment" key in sharedPreferences).
41+
boolean isLoadingActivity = this instanceof LoadingActivity;
42+
boolean isAccessActivity = this instanceof AccessActivity;
43+
if(!isLoadingActivity && !isAccessActivity && !((Global) getApplication()).areModelsLoaded()){
44+
//start LoadingActivity
45+
Intent intent = new Intent(this, LoadingActivity.class);
46+
intent.putExtra("activity", "general");
47+
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
48+
startActivity(intent);
49+
finish();
50+
}
51+
}
52+
3053
public void showMissingGoogleTTSDialog(@Nullable DialogInterface.OnClickListener continueListener) {
3154
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
3255
builder.setMessage(R.string.error_missing_tts);

app/src/main/java/nie/translator/rtranslator/Global.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ public class Global extends Application implements DefaultLifecycleObserver {
7272
Manifest.permission.RECORD_AUDIO,
7373
};
7474

75-
7675
public enum RTranslatorMode {
7776
TEXT_TRANSLATION_MODE,
7877
WALKIE_TALKIE_MODE,
@@ -105,6 +104,7 @@ public enum RTranslatorMode {
105104
private boolean useTatoeba;
106105
private boolean useTranslationDictionaries;
107106
private VadSilero vad;
107+
private boolean modelsLoaded = false;
108108

109109
@Override
110110
public void onCreate() {
@@ -205,6 +205,14 @@ public void onDestroyed() {
205205
});
206206
}
207207

208+
public boolean areModelsLoaded() {
209+
return modelsLoaded;
210+
}
211+
212+
public void setModelsLoaded(boolean areModelsLoaded) {
213+
this.modelsLoaded = areModelsLoaded;
214+
}
215+
208216
public void getLanguagesAndCheckTTS(final boolean recycleResult, boolean ignoreTTSError, final GetLocalesListListener responseListener) {
209217
if (recycleResult && !languages.isEmpty()) {
210218
responseListener.onSuccess(languages);

app/src/main/java/nie/translator/rtranslator/LoadingActivity.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.os.Handler;
2828
import android.os.Looper;
2929
import android.provider.Settings;
30+
import android.util.Log;
3031

3132
import androidx.appcompat.app.AlertDialog;
3233
import java.util.ArrayList;
@@ -57,7 +58,7 @@ public LoadingActivity() {
5758
protected void onCreate(Bundle savedInstanceState) {
5859
String previousActivity = getIntent().getStringExtra("activity");
5960
SplashScreen splashScreen = null;
60-
if(previousActivity == null || !previousActivity.equals("download")) { //if this activity is called by the DownloadFragment we don't use the splash screen
61+
if(previousActivity == null) { //if this activity is called by another activity (instead of on launch), we don't use the splash screen
6162
// Handle the splash screen transition (it must remain before the super.onCreate() call).
6263
splashScreen = SplashScreen.installSplashScreen(this);
6364
}
@@ -104,6 +105,7 @@ protected void onPause() {
104105
}
105106

106107
private void initializeApp(boolean ignoreTTSError) {
108+
Log.i("app", "App initialization");
107109
global.getLanguagesAndCheckTTS(false, ignoreTTSError, new Global.GetLocalesListListener() {
108110
@Override
109111
public void onSuccess(ArrayList<CustomLocale> result) {
@@ -113,6 +115,7 @@ public void onSuccess() {
113115
NeuralNetworkApi.InitListener speechRecognizerInitListener = new NeuralNetworkApi.InitListener() {
114116
@Override
115117
public void onInitializationFinished() {
118+
global.setModelsLoaded(true);
116119
if (isVisible) {
117120
startVoiceTranslationActivity();
118121
}

app/src/main/java/nie/translator/rtranslator/tools/ImageActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package nie.translator.rtranslator.tools;
22

3-
//This activity is used only to create the images of the conversation mode in the readme
4-
53
import android.app.Activity;
64
import android.content.Context;
75
import android.os.Bundle;
@@ -22,6 +20,8 @@
2220
import nie.translator.rtranslator.tools.gui.messages.GuiMessage;
2321
import nie.translator.rtranslator.tools.gui.messages.MessagesAdapter;
2422

23+
//This activity is used only to create the images of the conversation mode in the readme
24+
2525
public class ImageActivity extends Activity {
2626
protected MessagesAdapter mAdapter;
2727
protected RecyclerView mRecyclerView;

app/src/main/java/nie/translator/rtranslator/voice_translation/VoiceTranslationActivity.java

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package nie.translator.rtranslator.voice_translation;
1818

19-
import android.Manifest;
2019
import android.app.Notification;
2120
import android.app.PendingIntent;
2221
import android.content.Context;
@@ -25,11 +24,9 @@
2524
import android.content.SharedPreferences;
2625
import android.content.pm.PackageManager;
2726
import android.content.res.Configuration;
28-
import android.os.Build;
2927
import android.os.Bundle;
3028
import android.os.Handler;
3129
import android.os.Looper;
32-
import android.provider.Settings;
3330
import android.view.Menu;
3431
import android.view.MenuItem;
3532
import android.view.View;
@@ -50,6 +47,9 @@
5047
import androidx.fragment.app.Fragment;
5148
import androidx.fragment.app.FragmentManager;
5249
import androidx.fragment.app.FragmentTransaction;
50+
51+
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
52+
5353
import java.util.ArrayList;
5454
import java.util.List;
5555
import nie.translator.rtranslator.GeneralActivity;
@@ -86,7 +86,6 @@ public class VoiceTranslationActivity extends GeneralActivity {
8686
public static final int DEFAULT_FRAGMENT = TRANSLATION_FRAGMENT;
8787
//objects
8888
private Global global;
89-
private Fragment fragment;
9089
private CoordinatorLayout fragmentContainer;
9190
private int currentFragment = -1;
9291
private boolean startingPairing = false; //used to start Pairing Mode after bluetooth permissions are granted
@@ -139,7 +138,8 @@ protected void onStart() {
139138
super.onStart();
140139
// when we return to the app's gui based on the service that was saved in the last closure we choose which fragment to start
141140
SharedPreferences sharedPreferences = this.getSharedPreferences("default", Context.MODE_PRIVATE);
142-
setFragment(sharedPreferences.getInt("fragment", DEFAULT_FRAGMENT));
141+
int fragment = sharedPreferences.getInt("fragment", DEFAULT_FRAGMENT);
142+
setFragment(fragment, fragment == WALKIE_TALKIE_FRAGMENT || fragment == PAIRING_FRAGMENT);
143143
if(getResources() != null) {
144144
config = getResources().getConfiguration();
145145
}
@@ -165,14 +165,18 @@ public boolean onCreateOptionsMenu(Menu menu) {
165165
}
166166

167167
public void setFragment(int fragmentName) {
168+
setFragment(fragmentName, false);
169+
}
170+
171+
public void setFragment(int fragmentName, boolean requestPermission) {
168172
switch (fragmentName) {
169173
case PAIRING_FRAGMENT: {
170174
// possible stop of the Conversation and WalkieTalkie Service
171175
stopConversationService();
172176
stopWalkieTalkieService();
173177
// possible setting of the fragment
174-
if (getCurrentFragment() != PAIRING_FRAGMENT) {
175-
if (Tools.hasPermissions(this, Global.REQUIRED_PERMISSIONS_PAIRING)) {
178+
if (getCurrentFragmentId() != PAIRING_FRAGMENT) {
179+
if (Tools.hasPermissions(this, Global.REQUIRED_PERMISSIONS_PAIRING) || !requestPermission) {
176180
global.initializeBluetoothCommunicator();
177181
if(global.getBluetoothCommunicator() != null && global.getBluetoothCommunicator().isBluetoothLeSupported()){
178182
PairingFragment paringFragment = new PairingFragment();
@@ -198,7 +202,7 @@ public void setFragment(int fragmentName) {
198202
}
199203
case CONVERSATION_FRAGMENT: {
200204
// possible setting of the fragment
201-
if (getCurrentFragment() != CONVERSATION_FRAGMENT && global.getBluetoothCommunicator() != null) {
205+
if (getCurrentFragmentId() != CONVERSATION_FRAGMENT && global.getBluetoothCommunicator() != null) {
202206
ConversationFragment conversationFragment = new ConversationFragment();
203207
Bundle bundle = new Bundle();
204208
bundle.putBoolean("firstStart", true);
@@ -210,7 +214,7 @@ public void setFragment(int fragmentName) {
210214
currentFragment = CONVERSATION_FRAGMENT;
211215
saveFragment();
212216
// eventual permission request
213-
if (Tools.hasPermissions(this, Global.REQUIRED_PERMISSIONS_VOICE)) {
217+
if (!Tools.hasPermissions(this, Global.REQUIRED_PERMISSIONS_VOICE) && requestPermission) {
214218
showPermissionDialog(CONVERSATION_FRAGMENT);
215219
}
216220
//fragment= conversationFragment;
@@ -221,8 +225,8 @@ public void setFragment(int fragmentName) {
221225
}
222226
case WALKIE_TALKIE_FRAGMENT: {
223227
// possible setting of the fragment
224-
if (getCurrentFragment() != WALKIE_TALKIE_FRAGMENT) {
225-
if (Tools.hasPermissions(this, Global.REQUIRED_PERMISSIONS_VOICE)) {
228+
if (getCurrentFragmentId() != WALKIE_TALKIE_FRAGMENT) {
229+
if (Tools.hasPermissions(this, Global.REQUIRED_PERMISSIONS_VOICE) || !requestPermission) {
226230
WalkieTalkieFragment walkieTalkieFragment = new WalkieTalkieFragment();
227231
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
228232
Bundle bundle = new Bundle();
@@ -245,7 +249,7 @@ public void setFragment(int fragmentName) {
245249
stopConversationService();
246250
stopWalkieTalkieService();
247251
// possible setting of the fragment
248-
if (getCurrentFragment() != TRANSLATION_FRAGMENT) {
252+
if (getCurrentFragmentId() != TRANSLATION_FRAGMENT) {
249253
TranslationFragment translationFragment = new TranslationFragment();
250254
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
251255
Bundle bundle = new Bundle();
@@ -270,13 +274,13 @@ public void run() {
270274
//save fragment
271275
SharedPreferences sharedPreferences = VoiceTranslationActivity.this.getSharedPreferences("default", Context.MODE_PRIVATE);
272276
SharedPreferences.Editor editor = sharedPreferences.edit();
273-
editor.putInt("fragment", getCurrentFragment());
277+
editor.putInt("fragment", getCurrentFragmentId());
274278
editor.apply();
275279
}
276280
}.start();
277281
}
278282

279-
public int getCurrentFragment() {
283+
public int getCurrentFragmentId() {
280284
if (currentFragment != -1) {
281285
return currentFragment;
282286
} else {
@@ -299,6 +303,10 @@ public int getCurrentFragment() {
299303
return -1;
300304
}
301305

306+
public Fragment getCurrentFragment() {
307+
return getSupportFragmentManager().findFragmentById(R.id.fragment_container);
308+
}
309+
302310
@Override
303311
public void onConfigurationChanged(@NonNull Configuration newConfig) {
304312
super.onConfigurationChanged(newConfig);
@@ -382,22 +390,23 @@ public void disconnect(Peer peer) {
382390
}
383391

384392

385-
private void showPermissionDialog(int mode){
393+
public void showPermissionDialog(int mode){
386394
final View editDialogLayout = this.getLayoutInflater().inflate(R.layout.dialog_permission, null);
387395

388-
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
396+
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MyThemeOverlay_MaterialComponents_MaterialAlertDialog);
389397
builder.setCancelable(true);
390-
//builder.setTitle("");
391398

392399
AlertDialog dialog = builder.create();
393-
if (dialog.getWindow() != null) {
394-
// Requests the window to have no title
395-
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
396-
// Removes the default system background and padding
397-
dialog.getWindow().setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT));
398-
}
399400
dialog.setView(editDialogLayout, 0, Tools.convertDpToPixels(this, 16), 0, 0);
400401
dialog.show();
402+
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
403+
@Override
404+
public void onDismiss(DialogInterface dialog) {
405+
if(currentFragment == -1){
406+
setFragment(DEFAULT_FRAGMENT);
407+
}
408+
}
409+
});
401410

402411
ImageView icon = editDialogLayout.findViewById(R.id.dialogIcon);
403412
TextView text = editDialogLayout.findViewById(R.id.textView);
@@ -466,12 +475,17 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
466475
return;
467476
}
468477

478+
Fragment fragment = getCurrentFragment();
479+
469480
if(requestCode == Global.REQUEST_CODE_PERMISSIONS_PAIRING){
470481
for (int grantResult : grantResults) {
471482
if (grantResult == PackageManager.PERMISSION_DENIED) {
472483
//notifyMissingSearchPermission();
473484
Toast.makeText(global, R.string.error_missing_location_permissions, Toast.LENGTH_LONG).show();
474485
startingPairing = false;
486+
if(currentFragment == -1){
487+
setFragment(DEFAULT_FRAGMENT);
488+
}
475489
return;
476490
}
477491
}
@@ -486,10 +500,16 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
486500
if(requestCode == Global.REQUEST_CODE_PERMISSIONS_WALKIETALKIE){
487501
for (int grantResult : grantResults) {
488502
if (grantResult == PackageManager.PERMISSION_DENIED) {
503+
if(fragment instanceof VoiceTranslationFragment) ((VoiceTranslationFragment) fragment).onMicPermissionResult(false);
489504
//todo: convert the string to resource and translate it
490505
Toast.makeText(global, "It is not possible to use the WalkieTalkie mode without microphone permission, go to the settings to grant it, or reinstall the app", Toast.LENGTH_LONG).show();
491506
startingWalkieTalkie = false;
507+
if(currentFragment == -1){
508+
setFragment(DEFAULT_FRAGMENT);
509+
}
492510
return;
511+
}else{
512+
if(fragment instanceof VoiceTranslationFragment) ((VoiceTranslationFragment) fragment).onMicPermissionResult(true);
493513
}
494514
}
495515
//mic permission is granted
@@ -500,11 +520,21 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
500520
}
501521

502522
if(requestCode == Global.REQUEST_CODE_PERMISSIONS_CONVERSATION){
523+
ConversationMainFragment conversationFragment = null;
524+
if(fragment instanceof ConversationFragment){
525+
Fragment f = ((ConversationFragment) fragment).getCurrentFragment();
526+
if(f instanceof ConversationMainFragment){
527+
conversationFragment = (ConversationMainFragment) f;
528+
}
529+
}
503530
for (int grantResult : grantResults) {
504531
if (grantResult == PackageManager.PERMISSION_DENIED) {
532+
if(conversationFragment != null) conversationFragment.onMicPermissionResult(false);
505533
//todo: convert the string to resource and translate it
506534
Toast.makeText(global, R.string.error_missing_mic_permissions, Toast.LENGTH_LONG).show();
507535
return;
536+
}else{
537+
if(conversationFragment != null) conversationFragment.onMicPermissionResult(true);
508538
}
509539
}
510540
//mic permission is granted
@@ -574,7 +604,6 @@ public void startConversationService(Notification notification, final Global.Res
574604
}
575605
startService(intent);
576606
if(responseListener != null) responseListener.onSuccess();
577-
578607
}
579608

580609
public void startWalkieTalkieService(Notification notification, final Global.ResponseListener responseListener) {

0 commit comments

Comments
 (0)