Skip to content

Commit 5464a09

Browse files
committed
Added explanation screens for permissions
1. Added individual pages for granting permissions to storage and usage with explanations on why the permissions are needed Signed-off-by: pavan142 <[email protected]>
1 parent 95eb915 commit 5464a09

17 files changed

+531
-136
lines changed

app/build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ dependencies {
8181
implementation 'com.google.firebase:firebase-crashlytics'
8282
implementation 'com.google.firebase:firebase-perf'
8383

84+
// For Tab Layout
85+
implementation "com.google.android.material:material:1.3.0"
86+
implementation "androidx.viewpager2:viewpager2:1.0.0"
87+
88+
def fragment_version = "1.3.2"
89+
implementation "androidx.fragment:fragment:$fragment_version"
90+
8491
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
8592
testImplementation 'junit:junit:4.12'
8693
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'

app/src/main/java/com/frankenstein/screenx/MainActivity.java

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import androidx.core.app.ActivityCompat;
2222
import androidx.lifecycle.MutableLiveData;
2323
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
24+
import androidx.viewpager2.widget.ViewPager2;
2425

2526
import java.util.ArrayList;
2627

@@ -30,13 +31,17 @@
3031
import com.frankenstein.screenx.helper.PermissionHelper;
3132
import com.frankenstein.screenx.models.AppGroup;
3233
import com.frankenstein.screenx.models.Screenshot;
33-
import com.frankenstein.screenx.ui.PermissionComponentView;
3434
import com.frankenstein.screenx.ui.adapters.HomePageAdapter;
35+
import com.frankenstein.screenx.ui.adapters.PermissionPageAdapter;
36+
import com.google.android.material.tabs.TabLayout;
37+
import com.google.android.material.tabs.TabLayoutMediator;
3538

3639
import static com.frankenstein.screenx.Constants.PROGRESSBAR_TRANSITION;
3740
import static com.frankenstein.screenx.helper.ArrayHelper.Same;
3841
import static com.frankenstein.screenx.helper.FileHelper.CUSTOM_SCREENSHOT_DIR;
3942
import static com.frankenstein.screenx.helper.FileHelper.createIfNot;
43+
import static com.frankenstein.screenx.ui.adapters.PermissionPageAdapter.STORAGE_PERMISSION;
44+
import static com.frankenstein.screenx.ui.adapters.PermissionPageAdapter.USAGE_PERMISSION;
4045

4146
public class MainActivity extends AppCompatActivity {
4247

@@ -47,8 +52,7 @@ public class MainActivity extends AppCompatActivity {
4752
private SwipeRefreshLayout _pullToRefresh;
4853
private View _mProgressBar;
4954
private View _mPermissionsDisplay;
50-
private PermissionComponentView _mStoragePermissionsView;
51-
private PermissionComponentView _mUsagePermissionsView;
55+
private PermissionPageAdapter _mPermissionPageAdapter;
5256
private AlertDialog.Builder _mAlertBuilder;
5357

5458
private boolean _mPermissionsGranted = false;
@@ -98,12 +102,6 @@ protected void onCreate(Bundle savedInstanceState) {
98102

99103
_mPermissionsDisplay = findViewById(R.id.permissions_display);
100104

101-
_mStoragePermissionsView = findViewById(R.id.storage_permissions);
102-
_mStoragePermissionsView.setOnClickListener(view -> goToStorageSettings());
103-
104-
_mUsagePermissionsView = findViewById(R.id.usage_permissions);
105-
_mUsagePermissionsView.setOnClickListener(view -> goToUsageSettings());
106-
107105
_mAlertBuilder = new AlertDialog.Builder(this);
108106
setupSearchBar();
109107
_mState.observeForever(this::onStateChange);
@@ -127,8 +125,6 @@ private void setupSearchBar() {
127125
});
128126
}
129127

130-
131-
132128
private void onStateChange(HomePageState newState) {
133129
_mLogger.log("onStateChange", newState.toString());
134130
switch (newState) {
@@ -208,12 +204,23 @@ private void startScreenXService() {
208204
}
209205
}
210206

207+
private void onPermissionRequested(String permissionName) {
208+
switch (permissionName) {
209+
case STORAGE_PERMISSION:
210+
goToStorageSettings();
211+
break;
212+
case USAGE_PERMISSION:
213+
goToUsageSettings();
214+
break;
215+
}
216+
}
217+
211218
private void goToStorageSettings() {
212219
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE);
213220
}
214221

215222
private void goToUsageSettings() {
216-
if (_mUsagePermissionsView.hasPermission())
223+
if (PermissionHelper.hasUsagePermission(this))
217224
return;
218225
try {
219226
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
@@ -295,20 +302,32 @@ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
295302
});
296303
}
297304

305+
private void createPermissionAdapter() {
306+
if (_mPermissionPageAdapter != null)
307+
return;
308+
ViewPager2 permissionViewPager = findViewById(R.id.permission_view_pager);
309+
_mPermissionPageAdapter = new PermissionPageAdapter(this, this, this::onPermissionRequested);
310+
permissionViewPager.setAdapter(_mPermissionPageAdapter);
311+
TabLayout permissionTabLayout = findViewById(R.id.permission_tab_layout);
312+
new TabLayoutMediator(permissionTabLayout, permissionViewPager, (tab, pos) -> {}).attach();
313+
}
314+
298315
public void checkPermissions() {
299-
boolean storagePermissions = PermissionHelper.hasStoragePermission(this);
300-
boolean usagePermissions = PermissionHelper.hasUsagePermission(this);
316+
boolean hasStoragePermission = PermissionHelper.hasStoragePermission(this);
317+
boolean hasUsagePermission = PermissionHelper.hasUsagePermission(this);
301318

302-
if (storagePermissions && usagePermissions) {
319+
if (hasStoragePermission && hasUsagePermission) {
303320
_mLogger.log("Has all the permissions");
304321
_mState.setValue(HomePageState.LOADING_PROGRESS_BAR);
305322
return;
306323
}
307324

308-
_mStoragePermissionsView.onPermissionChanged(storagePermissions);
309-
_mUsagePermissionsView.onPermissionChanged(usagePermissions);
325+
createPermissionAdapter();
326+
327+
_mPermissionPageAdapter.onPermissionChanged(STORAGE_PERMISSION, hasStoragePermission);
328+
_mPermissionPageAdapter.onPermissionChanged(USAGE_PERMISSION, hasUsagePermission);
310329

311-
_mLogger.log("Permissions Missing:: storage ->", storagePermissions, " usage ->", usagePermissions);
330+
_mLogger.log("Permissions Missing:: storage ->", hasStoragePermission, " usage ->", hasUsagePermission);
312331
}
313332

314333
@Override

app/src/main/java/com/frankenstein/screenx/ScreenFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ public void addScreen(Screenshot screen) {
143143

144144
public void onScreenAdded(Context context, String filepath) {
145145
_monitorHandler.post(() -> {
146+
if (screenshots.getValue() == null)
147+
return;
146148
_logger.log("ScreenFactory: onScreenAdded", filepath);
147149
File file = new File(filepath);
148150
if (nameToScreen.containsKey(file.getName())) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.frankenstein.screenx.models;
2+
3+
4+
import android.graphics.drawable.Drawable;
5+
6+
import androidx.lifecycle.MutableLiveData;
7+
8+
public class PermissionDetail {
9+
public String name;
10+
public String title;
11+
public Drawable drawable;
12+
public String description;
13+
public MutableLiveData<Boolean> hasPermission = new MutableLiveData<>(false);
14+
public PermissionRequestListener listener;
15+
16+
public PermissionDetail(String name, String title, Drawable drawable, String description, PermissionRequestListener listener) {
17+
this.name = name;
18+
this.title = title;
19+
this.drawable = drawable;
20+
this.description = description;
21+
this.listener = listener;
22+
}
23+
24+
public interface PermissionRequestListener {
25+
void onPermissionRequested(String permissionName);
26+
}
27+
}

app/src/main/java/com/frankenstein/screenx/ui/PermissionComponentView.java

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.frankenstein.screenx.ui;
2+
3+
import android.os.Bundle;
4+
import android.view.LayoutInflater;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
import android.widget.ImageView;
8+
import android.widget.TextView;
9+
10+
import com.frankenstein.screenx.R;
11+
import com.frankenstein.screenx.helper.Logger;
12+
import com.frankenstein.screenx.models.PermissionDetail;
13+
import com.frankenstein.screenx.ui.adapters.PermissionPageAdapter;
14+
15+
16+
import androidx.annotation.NonNull;
17+
import androidx.annotation.Nullable;
18+
import androidx.fragment.app.Fragment;
19+
20+
public class PermissionDetailFragment extends Fragment {
21+
private PermissionDetail _mDetail;
22+
private TextView _mTitle;
23+
private TextView _mDescription;
24+
private ImageView _mImage;
25+
private TextView _mPermissionButton;
26+
private static final Logger _mLogger = Logger.getInstance("PermissionDetailFragment");
27+
public static final String PERMISSION_NAME="PERMISSION_NAME";
28+
29+
public PermissionDetailFragment () {
30+
super();
31+
}
32+
33+
@Nullable
34+
@Override
35+
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
36+
super.onCreateView(inflater, container, savedInstanceState);
37+
View view = inflater.inflate(R.layout.homepage_permissions_component, container, false);
38+
_mTitle = view.findViewById(R.id.permission_title);
39+
_mDescription = view.findViewById(R.id.permission_description);
40+
_mImage = view.findViewById(R.id.permission_image);
41+
_mPermissionButton = view.findViewById(R.id.grant_permissions);
42+
Bundle bundle = getArguments();
43+
String permissionName = bundle.getString(PERMISSION_NAME);
44+
_mDetail = PermissionPageAdapter.detailsMap.get(permissionName);
45+
return view;
46+
}
47+
48+
@Override
49+
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
50+
onPermissionsChanged(_mDetail.hasPermission.getValue());
51+
_mDetail.hasPermission.observe(getViewLifecycleOwner(), this::onPermissionsChanged);
52+
_mPermissionButton.setOnClickListener((v) -> {
53+
_mDetail.listener.onPermissionRequested(_mDetail.name);
54+
});
55+
_mTitle.setText(_mDetail.title);
56+
_mDescription.setText(_mDetail.description);
57+
_mImage.setImageDrawable(_mDetail.drawable);
58+
super.onViewCreated(view, savedInstanceState);
59+
}
60+
61+
public void onPermissionsChanged(boolean hasPermission) {
62+
_mLogger.log("onPermissionsChanged", _mDetail.name, hasPermission);
63+
if (!hasPermission)
64+
_mPermissionButton.setText(getActivity().getResources().getText(R.string.grant_permissions));
65+
else
66+
_mPermissionButton.setText(getActivity().getResources().getText(R.string.permissions_granted));
67+
}
68+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.frankenstein.screenx.ui.adapters;
2+
3+
import android.content.Context;
4+
import android.os.Bundle;
5+
6+
import com.frankenstein.screenx.R;
7+
import com.frankenstein.screenx.helper.Logger;
8+
import com.frankenstein.screenx.models.PermissionDetail;
9+
import com.frankenstein.screenx.models.PermissionDetail.PermissionRequestListener;
10+
import com.frankenstein.screenx.ui.PermissionDetailFragment;
11+
12+
import java.util.ArrayList;
13+
import java.util.HashMap;
14+
import java.util.Map;
15+
16+
import androidx.annotation.NonNull;
17+
import androidx.fragment.app.Fragment;
18+
import androidx.fragment.app.FragmentActivity;
19+
import androidx.viewpager2.adapter.FragmentStateAdapter;
20+
21+
public class PermissionPageAdapter extends FragmentStateAdapter {
22+
23+
private Logger _logger = Logger.getInstance("PermissionPageAdapter");
24+
public static final Map<String, PermissionDetail> detailsMap = new HashMap<>();
25+
private final ArrayList<String> _permissionOrder = new ArrayList<>();
26+
private PermissionRequestListener _listener;
27+
public static final String STORAGE_PERMISSION = "STORAGE_PERMISSION";
28+
public static final String USAGE_PERMISSION = "USAGE_PERMISSION";
29+
30+
public PermissionPageAdapter(FragmentActivity fa, Context context, PermissionRequestListener listener) {
31+
super(fa);
32+
this._listener = listener;
33+
detailsMap.put(STORAGE_PERMISSION,new PermissionDetail(
34+
STORAGE_PERMISSION,
35+
context.getResources().getString(R.string.storage_permission_title),
36+
context.getResources().getDrawable(R.drawable.ic_storage),
37+
context.getResources().getString(R.string.storage_permission_description),
38+
listener
39+
));
40+
detailsMap.put(USAGE_PERMISSION,new PermissionDetail(
41+
USAGE_PERMISSION,
42+
context.getResources().getString(R.string.usage_permission_title),
43+
context.getResources().getDrawable(R.drawable.ic_usage),
44+
context.getResources().getString(R.string.usage_permission_description),
45+
listener
46+
));
47+
_permissionOrder.add(STORAGE_PERMISSION);
48+
_permissionOrder.add(USAGE_PERMISSION);
49+
}
50+
51+
@Override
52+
public int getItemCount() {
53+
return _permissionOrder.size();
54+
}
55+
56+
@NonNull
57+
@Override
58+
public Fragment createFragment(int position) {
59+
_logger.log("View Pager Instantiating item", position);
60+
String permissionName = _permissionOrder.get(position);
61+
PermissionDetailFragment fragment = new PermissionDetailFragment();
62+
Bundle bundle = new Bundle();
63+
bundle.putString(PermissionDetailFragment.PERMISSION_NAME, permissionName);
64+
fragment.setArguments(bundle);
65+
return fragment;
66+
}
67+
68+
public void onPermissionChanged(String permissionName, boolean hasPermission) {
69+
_logger.log("onPermissionChanged", permissionName, hasPermission);
70+
PermissionDetail detail = detailsMap.get(permissionName);
71+
detail.hasPermission.setValue(hasPermission);
72+
}
73+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layer-list
3+
xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item>
5+
<shape
6+
android:innerRadius="0dp"
7+
android:shape="ring"
8+
android:thickness="@dimen/tab_dot_size"
9+
android:useLevel="false">
10+
<solid android:color="@android:color/darker_gray"/>
11+
</shape>
12+
</item>
13+
</layer-list>

0 commit comments

Comments
 (0)