onActivityResult not being called when Preference Fragment calls it as a parent

79 Views Asked by At

My app records GNSS positions as a tool to produce Orienteering's map using a cell phone. The main activity does all the job and when the mapper needs to export the field job done, app calls a child activity (Save_File) responsible to save on Documents/Oribooklet directory a file, using gpx format. Because of getExternalStoragePublicDirectory obsolescence, SAF is the way to choose to go. I am not an IT guy, I did this for fun, that is why I am so late with this matter: users drop me messages saying they couldn't save the field job anymore.

Main: Oribooklet

public class Oribooklet extends AppCompatActivity {

...

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Mapper clicked on a menu option in the app bar overflow menu
    Intent intent;
    switch (item.getItemId()) {

        // Respond to a click on the "Save" menu option
        case R.id.action_saveFile:
            // Call the Save_File Class
            // Prepare to show Save UI

            // Save to Shared Preference
            SharedPreferences sharedPref = getSharedPreferences("user_preferences", MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPref.edit();
            editor.putBoolean("bShowSaveUI", true);
            editor.apply();

            intent = new Intent(Oribooklet.this, Save_File.class);
            startActivity(intent);
            return true;

        // Respond to a click on the "Preference" menu option
        case R.id.action_settings:
            // Call the Class Activity_Preference for options menu
            intent  = new Intent(Oribooklet.this,Activity_Preference.class);
            startActivity(intent);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

Inside Save_File activity I implemented and it worked fine: when the mapper push Save, startActivityForResult is triggered, then an Android file picker starts, mapper choose where to save.

void createExternalStoragePublicDocument(String fileName) {

    try {
        // Call SAF
        Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType(INTENT_TYPE);
        intent.putExtra(Intent.EXTRA_TITLE, fileName);

        // https://stackoverflow.com/questions/6147884/onactivityresult-is-not-being-called-in-fragment
        startActivityForResult(intent, CREATE_REQUEST_CODE);
    } catch (Exception excep) {
        excep.printStackTrace();
    }
}

Then onActivityResult gets the returned Uri to complete the job by filling the file with the data collected on the field. Couldn't be any better!

    @Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    super.onActivityResult(requestCode, resultCode, resultData);
    Uri currentUri = null;
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == CREATE_REQUEST_CODE) {
            if (resultData != null) {
                currentUri = resultData.getData();
                // Write contents
                writeFileContent(currentUri, fileData);
            }
        } else if (requestCode == OPEN_REQUEST_CODE) {
            if (resultData != null) {
                currentUri = resultData.getData();
                sendByMail(stringEMailAddress, stringSubject, currentUri);
                // Back to Oribooklet
                finish();
            }
        }
    }
}

The app has a Preference fragment to set up some parameters. One of them is the standard to be used. Two standards must not be mixed doing a map. When the mapper changes the map's type, Preference used to call Save_File to do the job so no mix of data happens. It used to work fine.

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
                                      final String key) {
    // Find the one that changed and address it
    Preference connectionPref = findPreference(key);
    switch (key){
        case "list_iof":
            // IOF´s element set
            SharedPreferences preferences = getActivity().getSharedPreferences("user_preferences", MODE_PRIVATE);

            // Update preference Summary
            ListPreference listIOFPreference = (ListPreference) findPreference("list_iof");
            CharSequence iof = listIOFPreference.getEntry();
            connectionPref.setSummary(getResources().getString(R.string.pref_iof_summary_1) +
                    iof + "\" " +
                    getResources().getString(R.string.pref_iof_summary_2));
            // Save the field job to avoid IOF set mixing
            Intent intent = new Intent(getActivity(), Save_File.class);
            startActivity(intent);
            break;

After SAF, the onActivityResult of Save_File is never triggered, startActivityForResult triggers the file provider but when the mapper chooses the place to save, instead of onActivityResult of Save_File it returns to Preference so the file is created empty.

I did many tests, debugging with many breaking points, setting and removing super in quite a few places, checked all S.O. posts about the matter without success.

Any idea?

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_oribooklet_v0"
android:name=".MyAppContext"

android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
    <!--android:requestLegacyExternalStore="true" -->

    <!-- android:roundIcon="@mipmap/ic_oribooklet_v2"-->

    <activity android:name="com.hbcavalcanti.oribooklet.Oribooklet"
              android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <!-- A child of the main activity -->
    <activity
        android:name=".Save_File"
        android:label="@string/action_saveFile"
        android:parentActivityName=".Oribooklet" >

        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".Oribooklet" />
    </activity>

    <activity
        android:name=".Activity_Preference"
        android:label="@string/action_settings"
        android:parentActivityName=".Oribooklet" >

        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".Oribooklet" />
    </activity>

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.hbcavalcanti.oribooklet.fileprovider"
        android:grantUriPermissions="true"
        android:exported="false">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/filepaths" />
    </provider>
</application>
1

There are 1 best solutions below

0
On

When called from Preference, the Save File method used not to make any UI call, then its onActivityResult was never called.

Just for test purpose, I introduced one onActivityResult on Preference fragment and it received a trigger. I removed after the test.

I fixed the issue by also calling an UI inside Save File when Preference invoque it. This trigger its onActivityResult making everything works fine like being called from its parent.