33import android .content .ActivityNotFoundException ;
44import android .content .DialogInterface ;
55import android .content .Intent ;
6+ import android .content .pm .PackageManager ;
67import android .net .Uri ;
78import android .os .Bundle ;
89import android .text .InputType ;
1718
1819import androidx .activity .result .ActivityResultLauncher ;
1920import androidx .activity .result .contract .ActivityResultContracts ;
21+ import androidx .annotation .NonNull ;
2022import androidx .annotation .Nullable ;
2123import androidx .appcompat .app .AlertDialog ;
2224import androidx .appcompat .widget .Toolbar ;
25+ import androidx .work .Data ;
26+ import androidx .work .OneTimeWorkRequest ;
27+ import androidx .work .OutOfQuotaPolicy ;
28+ import androidx .work .WorkManager ;
29+ import androidx .work .WorkRequest ;
2330
2431import com .google .android .material .dialog .MaterialAlertDialogBuilder ;
2532import com .google .android .material .textfield .TextInputLayout ;
2835import java .io .InputStream ;
2936import java .io .OutputStream ;
3037import java .util .ArrayList ;
38+ import java .util .Arrays ;
3139import java .util .List ;
3240
3341import protect .card_locker .async .TaskHandler ;
3442import protect .card_locker .databinding .ImportExportActivityBinding ;
3543import protect .card_locker .importexport .DataFormat ;
3644import protect .card_locker .importexport .ImportExportResult ;
3745import protect .card_locker .importexport .ImportExportResultType ;
46+ import protect .card_locker .importexport .ImportExportWorker ;
3847
3948public class ImportExportActivity extends CatimaAppCompatActivity {
4049 private ImportExportActivityBinding binding ;
4150 private static final String TAG = "Catima" ;
4251
43- private ImportExportTask importExporter ;
44-
4552 private String importAlertTitle ;
4653 private String importAlertMessage ;
4754 private DataFormat importDataFormat ;
@@ -51,7 +58,10 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
5158 private ActivityResultLauncher <String > fileOpenLauncher ;
5259 private ActivityResultLauncher <Intent > filePickerLauncher ;
5360
54- final private TaskHandler mTasks = new TaskHandler ();
61+ private static final int PERMISSION_REQUEST_EXPORT = 100 ;
62+ private static final int PERMISSION_REQUEST_IMPORT = 101 ;
63+
64+ private WorkRequest mRequestedWorkRequest ;
5565
5666 @ Override
5767 protected void onCreate (Bundle savedInstanceState ) {
@@ -80,15 +90,20 @@ protected void onCreate(Bundle savedInstanceState) {
8090 Log .e (TAG , "Activity returned NULL uri" );
8191 return ;
8292 }
83- try {
84- OutputStream writer = getContentResolver ().openOutputStream (uri );
85- Log .e (TAG , "Starting file export with: " + result .toString ());
86- startExport (writer , uri , exportPassword .toCharArray (), true );
87- } catch (IOException e ) {
88- Log .e (TAG , "Failed to export file: " + result .toString (), e );
89- onExportComplete (new ImportExportResult (ImportExportResultType .GenericFailure , result .toString ()), uri );
90- }
9193
94+ Data exportRequestData = new Data .Builder ()
95+ .putString (ImportExportWorker .INPUT_URI , uri .toString ())
96+ .putString (ImportExportWorker .INPUT_ACTION , ImportExportWorker .ACTION_EXPORT )
97+ .putString (ImportExportWorker .INPUT_FORMAT , DataFormat .Catima .name ())
98+ .putString (ImportExportWorker .INPUT_PASSWORD , exportPassword )
99+ .build ();
100+
101+ mRequestedWorkRequest = new OneTimeWorkRequest .Builder (ImportExportWorker .class )
102+ .setInputData (exportRequestData )
103+ .setExpedited (OutOfQuotaPolicy .RUN_AS_NON_EXPEDITED_WORK_REQUEST )
104+ .build ();
105+
106+ PermissionUtils .requestPostNotificationsPermission (this , PERMISSION_REQUEST_EXPORT );
92107 });
93108 fileOpenLauncher = registerForActivityResult (new ActivityResultContracts .GetContent (), result -> {
94109 if (result == null ) {
@@ -160,14 +175,19 @@ protected void onCreate(Bundle savedInstanceState) {
160175 }
161176
162177 private void openFileForImport (Uri uri , char [] password ) {
163- try {
164- InputStream reader = getContentResolver ().openInputStream (uri );
165- Log .e (TAG , "Starting file import with: " + uri .toString ());
166- startImport (reader , uri , importDataFormat , password , true );
167- } catch (IOException e ) {
168- Log .e (TAG , "Failed to import file: " + uri .toString (), e );
169- onImportComplete (new ImportExportResult (ImportExportResultType .GenericFailure , e .toString ()), uri , importDataFormat );
170- }
178+ Data importRequestData = new Data .Builder ()
179+ .putString (ImportExportWorker .INPUT_URI , uri .toString ())
180+ .putString (ImportExportWorker .INPUT_ACTION , ImportExportWorker .ACTION_IMPORT )
181+ .putString (ImportExportWorker .INPUT_FORMAT , importDataFormat .name ())
182+ .putString (ImportExportWorker .INPUT_PASSWORD , Arrays .toString (password ))
183+ .build ();
184+
185+ mRequestedWorkRequest = new OneTimeWorkRequest .Builder (ImportExportWorker .class )
186+ .setInputData (importRequestData )
187+ .setExpedited (OutOfQuotaPolicy .RUN_AS_NON_EXPEDITED_WORK_REQUEST )
188+ .build ();
189+
190+ PermissionUtils .requestPostNotificationsPermission (this , PERMISSION_REQUEST_IMPORT );
171191 }
172192
173193 private void chooseImportType (boolean choosePicker ,
@@ -232,20 +252,17 @@ private void chooseImportType(boolean choosePicker,
232252 new MaterialAlertDialogBuilder (this )
233253 .setTitle (importAlertTitle )
234254 .setMessage (importAlertMessage )
235- .setPositiveButton (R .string .ok , new DialogInterface .OnClickListener () {
236- @ Override
237- public void onClick (DialogInterface dialog , int which ) {
238- try {
239- if (choosePicker ) {
240- final Intent intentPickAction = new Intent (Intent .ACTION_PICK );
241- filePickerLauncher .launch (intentPickAction );
242- } else {
243- fileOpenLauncher .launch ("*/*" );
244- }
245- } catch (ActivityNotFoundException e ) {
246- Toast .makeText (getApplicationContext (), R .string .failedOpeningFileManager , Toast .LENGTH_LONG ).show ();
247- Log .e (TAG , "No activity found to handle intent" , e );
255+ .setPositiveButton (R .string .ok , (dialog1 , which1 ) -> {
256+ try {
257+ if (choosePicker ) {
258+ final Intent intentPickAction = new Intent (Intent .ACTION_PICK );
259+ filePickerLauncher .launch (intentPickAction );
260+ } else {
261+ fileOpenLauncher .launch ("*/*" );
248262 }
263+ } catch (ActivityNotFoundException e ) {
264+ Toast .makeText (getApplicationContext (), R .string .failedOpeningFileManager , Toast .LENGTH_LONG ).show ();
265+ Log .e (TAG , "No activity found to handle intent" , e );
249266 }
250267 })
251268 .setNegativeButton (R .string .cancel , null )
@@ -254,55 +271,6 @@ public void onClick(DialogInterface dialog, int which) {
254271 builder .show ();
255272 }
256273
257- private void startImport (final InputStream target , final Uri targetUri , final DataFormat dataFormat , final char [] password , final boolean closeWhenDone ) {
258- mTasks .flushTaskList (TaskHandler .TYPE .IMPORT , true , false , false );
259- ImportExportTask .TaskCompleteListener listener = new ImportExportTask .TaskCompleteListener () {
260- @ Override
261- public void onTaskComplete (ImportExportResult result , DataFormat dataFormat ) {
262- onImportComplete (result , targetUri , dataFormat );
263- if (closeWhenDone ) {
264- try {
265- target .close ();
266- } catch (IOException ioException ) {
267- ioException .printStackTrace ();
268- }
269- }
270- }
271- };
272-
273- importExporter = new ImportExportTask (ImportExportActivity .this ,
274- dataFormat , target , password , listener );
275- mTasks .executeTask (TaskHandler .TYPE .IMPORT , importExporter );
276- }
277-
278- private void startExport (final OutputStream target , final Uri targetUri , char [] password , final boolean closeWhenDone ) {
279- mTasks .flushTaskList (TaskHandler .TYPE .EXPORT , true , false , false );
280- ImportExportTask .TaskCompleteListener listener = new ImportExportTask .TaskCompleteListener () {
281- @ Override
282- public void onTaskComplete (ImportExportResult result , DataFormat dataFormat ) {
283- onExportComplete (result , targetUri );
284- if (closeWhenDone ) {
285- try {
286- target .close ();
287- } catch (IOException ioException ) {
288- ioException .printStackTrace ();
289- }
290- }
291- }
292- };
293-
294- importExporter = new ImportExportTask (ImportExportActivity .this ,
295- DataFormat .Catima , target , password , listener );
296- mTasks .executeTask (TaskHandler .TYPE .EXPORT , importExporter );
297- }
298-
299- @ Override
300- protected void onDestroy () {
301- mTasks .flushTaskList (TaskHandler .TYPE .IMPORT , true , false , false );
302- mTasks .flushTaskList (TaskHandler .TYPE .EXPORT , true , false , false );
303- super .onDestroy ();
304- }
305-
306274 @ Override
307275 public boolean onOptionsItemSelected (MenuItem item ) {
308276 int id = item .getItemId ();
@@ -343,68 +311,39 @@ private void retryWithPassword(DataFormat dataFormat, Uri uri) {
343311 builder .show ();
344312 }
345313
346- private String buildResultDialogMessage (ImportExportResult result , boolean isImport ) {
347- int messageId ;
348-
349- if (result .resultType () == ImportExportResultType .Success ) {
350- messageId = isImport ? R .string .importSuccessful : R .string .exportSuccessful ;
351- } else {
352- messageId = isImport ? R .string .importFailed : R .string .exportFailed ;
353- }
354-
355- StringBuilder messageBuilder = new StringBuilder (getResources ().getString (messageId ));
356- if (result .developerDetails () != null ) {
357- messageBuilder .append ("\n \n " );
358- messageBuilder .append (getResources ().getString (R .string .include_if_asking_support ));
359- messageBuilder .append ("\n \n " );
360- messageBuilder .append (result .developerDetails ());
361- }
362-
363- return messageBuilder .toString ();
364- }
365-
366- private void onImportComplete (ImportExportResult result , Uri path , DataFormat dataFormat ) {
367- ImportExportResultType resultType = result .resultType ();
368-
369- if (resultType == ImportExportResultType .BadPassword ) {
370- retryWithPassword (dataFormat , path );
371- return ;
372- }
373-
374- AlertDialog .Builder builder = new MaterialAlertDialogBuilder (this );
375- builder .setTitle (resultType == ImportExportResultType .Success ? R .string .importSuccessfulTitle : R .string .importFailedTitle );
376- builder .setMessage (buildResultDialogMessage (result , true ));
377- builder .setNeutralButton (R .string .ok , (dialog , which ) -> dialog .dismiss ());
314+ @ Override
315+ public void onRequestPermissionsResult (int requestCode , @ NonNull String [] permissions , @ NonNull int [] grantResults ) {
316+ super .onRequestPermissionsResult (requestCode , permissions , grantResults );
378317
379- builder . create (). show ( );
318+ onMockedRequestPermissionsResult ( requestCode , permissions , grantResults );
380319 }
381320
382- private void onExportComplete (ImportExportResult result , final Uri path ) {
383- ImportExportResultType resultType = result .resultType ();
321+ public void onMockedRequestPermissionsResult (int requestCode , @ NonNull String [] permissions , @ NonNull int [] grantResults ) {
322+ boolean granted = grantResults .length > 0 && grantResults [0 ] == PackageManager .PERMISSION_GRANTED ;
323+ Integer failureReason = null ;
384324
385- AlertDialog .Builder builder = new MaterialAlertDialogBuilder (this );
386- builder .setTitle (resultType == ImportExportResultType .Success ? R .string .exportSuccessfulTitle : R .string .exportFailedTitle );
387- builder .setMessage (buildResultDialogMessage (result , false ));
388- builder .setNeutralButton (R .string .ok , (dialog , which ) -> dialog .dismiss ());
325+ if (requestCode == PERMISSION_REQUEST_EXPORT ) {
326+ if (granted ) {
327+ WorkManager .getInstance (this ).enqueue (mRequestedWorkRequest );
389328
390- if (resultType == ImportExportResultType .Success ) {
391- final CharSequence sendLabel = ImportExportActivity .this .getResources ().getText (R .string .sendLabel );
392-
393- builder .setPositiveButton (sendLabel , (dialog , which ) -> {
394- Intent sendIntent = new Intent (Intent .ACTION_SEND );
395- sendIntent .putExtra (Intent .EXTRA_STREAM , path );
396- sendIntent .setType ("text/csv" );
329+ Toast .makeText (this , R .string .exportStartedCheckNotifications , Toast .LENGTH_LONG ).show ();
330+ return ;
331+ }
397332
398- // set flag to give temporary permission to external app to use the FileProvider
399- sendIntent .setFlags (Intent .FLAG_GRANT_READ_URI_PERMISSION );
333+ failureReason = R .string .postNotificationsPermissionRequired ;
334+ } else if (requestCode == PERMISSION_REQUEST_IMPORT ) {
335+ if (granted ) {
336+ WorkManager .getInstance (this ).enqueue (mRequestedWorkRequest );
400337
401- ImportExportActivity .this .startActivity (Intent .createChooser (sendIntent ,
402- sendLabel ));
338+ Toast .makeText (this , R .string .importStartedCheckNotifications , Toast .LENGTH_LONG ).show ();
339+ return ;
340+ }
403341
404- dialog .dismiss ();
405- });
342+ failureReason = R .string .postNotificationsPermissionRequired ;
406343 }
407344
408- builder .create ().show ();
345+ if (failureReason != null ) {
346+ Toast .makeText (this , failureReason , Toast .LENGTH_LONG ).show ();
347+ }
409348 }
410349}
0 commit comments