Why Essentials.Launcher does not have "alway" option

aluzi liu 486 Reputation points
2022-01-17T11:06:04.397+00:00

I use Essentials.Launcher to launcher a file with system installed app,code:

                    string u = "...........";
                    string fileName = "xxx";
                    string path = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/{fileName}";
                    Stream stream = await http.GetStreamAsync(u);//http is HttpClient
                    if (File.Exists(path))
                        File.Delete(path);
                    FileStream fs = new FileStream(path, FileMode.Create);
                    stream.CopyTo(fs);
                    fs.Close();
                    stream.Close();

                    await Launcher.OpenAsync(new OpenFileRequest
                    {
                        File = new ReadOnlyFile(path)
                    });

The code works, but app listing dialog missing "once" and "alway" option, each time I want to open file, it will prompt a dialog, I have to choose every time.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,296 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 68,656 Reputation points Microsoft Vendor
    2022-01-19T03:11:06.857+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    but after I choose a app to launch, the app I chosen tell me "can not find the file", Where am I doing wrong?

    I create a txt file, then store it in the /data/user/0/com.companyname.app9/files/File.txt, I use your code, then use Chrome to open it, I get the file cannot access. Then I find wo places need to be changed. I can open the test text file normally.

    Firstly, you need to grand Read/Write Url flags in your Intent like following code, If you want your files could be opened by other application.

       intent.AddFlags(ActivityFlags.GrantReadUriPermission);  
         intent.AddFlags(ActivityFlags.GrantWriteUriPermission);  
    

    Second, I notice you used android.support.v4.content in the <provider>, If you set the target framework to Android 10 or later, you need to change it like following code. You can refer to this link about Android File Provider Setup

       <application android:label="App7.Android" android:theme="@style/MainTheme">  
       		<provider android:name="androidx.core.content.FileProvider"  
       				  android:authorities="${applicationId}.fileprovider"  
       				  android:exported="false"  
       				  android:grantUriPermissions="true">  
         
       			<meta-data android:name="android.support.FILE_PROVIDER_PATHS"  
       						   android:resource="@xml/provider_paths"></meta-data>  
       		</provider>  
       	</application>  
    

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


2 additional answers

Sort by: Most helpful
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 68,656 Reputation points Microsoft Vendor
    2022-01-18T06:34:58.897+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    This dialog pop up by the Android OS, this is not a dialog you can control from your app.

    we can open the source code of Launcher.OpenAsync on android platform to check the root cause.

    The problem is that PlatformOpenAsync(OpenFileRequest request) calling Intent.CreateChooser , which is not intended to let the user change their default but is instead intended to force the user to choose.

    Chooser will always show up because that's its role - to let user choose.

    The Always | Just once functionality is different thing -> it is a feature of the Android framework for startActivity() (and startActivityForResult() etc) and it would show up automatically when needed (when there's more than one app, or precisely, more than one matching intent-filter declared in app manifest, that matches certain Intent). It would not show up if you got just one (or if user already choose Always).

    We do not need to care nor handle the case in any special way. Here is a similar thread.

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

  2. aluzi liu 486 Reputation points
    2022-01-18T10:16:20.557+00:00

    Thanks.
    But I need "alway" option, what can I do?

    I tried wrote a dependency service

                        string fileName = "xxx";  
                        string u = "xxxxx";  
                        string path = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/{fileName}";  
                        Stream stream = await http.GetStreamAsync(u);  
                        if (File.Exists(path))  
                            File.Delete(path);  
                        FileStream fs = new FileStream(path, FileMode.Create);  
                        stream.CopyTo(fs);  
                        fs.Close();  
                        stream.Close();  
      
                        DependencyService.Get<ILauncher>().LaunchFile(path);  
    

    The "LaunchFile" is:

            public void LaunchFile(string path)  
            {  
                var context = MainActivity.Instance.ApplicationContext;  
                Intent intent = new Intent(Intent.ActionView);  
                Java.IO.File file=new Java.IO.File(path);  
                Uri u= FileProvider.GetUriForFile(MainActivity.Instance.ApplicationContext, "com.companyname.app9.fileprovider", file);  
                  
                intent.SetData(u);  
                intent.AddFlags(ActivityFlags.ClearWhenTaskReset);  
                intent.AddFlags(ActivityFlags.NewTask);  
      
                MainActivity.Instance.ApplicationContext.StartActivity(intent);  
            }  
    

    File provider is :

    		<provider  
    			   android:name="android.support.v4.content.FileProvider"  
    			   android:authorities="${applicationId}.fileprovider"  
    			   android:exported="false"  
    			   android:grantUriPermissions="true">  
    			<meta-data  
    				android:name="android.support.FILE_PROVIDER_PATHS"  
    				android:resource="@xml/provider_paths"/>  
    		</provider>  
    

    xml file is:

    <?xml version="1.0" encoding="utf-8" ?>  
    <paths xmlns:android="http://schemas.android.com/apk/res/android">  
    	<files-path name="files" path="."/>	  
    </paths>  
    

    Then I can see the "alway" option in pop up dialog, but after I choose a app to launch, the app I chosen tell me "can not find the file", Where am I doing wrong?
    asdasd