2017-10-03 4 views
0

Je développe une application Android en utilisant Xamarin.Forms. Jusqu'ici je n'ai pas trouvé trop de difficultés pendant le développement, mais maintenant je pense qu'il me manque quelque chose.Partager un fichier vers une autre application (WhatsApp, télégramme, Gmail)

Je voudrais:

  1. partager un fichier personnalisé (* .sl) de mon application à une application qui peut gérer les pièces jointes (comme WhatsApp, télégramme, gmail .. etc)
  2. Ouvrez mon fichier personnalisé (* .sl) avec mon application

Ainsi, j'ai creusé un peu autour du web et fini avec ceci;

Dans mon AndroidManifest.xml pour gérer mon dossier personnalisé

<intent-filter> 
    <action android:name="android.intent.action.VIEW" /> 
    <category android:name="android.intent.category.BROWSABLE" /> 
    <category android:name="android.intent.category.DEFAULT" /> 
    <data android:scheme="file" /> 
    <data android:host="*" /> 
    <data android:mimeType="*/*" /> 
    <data android:pathPattern=".*\.sl" /> 
    </intent-filter> 
    <intent-filter> 
    <action android:name="android.intent.action.VIEW" /> 
    <category android:name="android.intent.category.BROWSABLE" /> 
    <category android:name="android.intent.category.DEFAULT" /> 
    <data android:scheme="content" /> 
    <data android:mimeType="application/octet-stream" /> 
    <data android:mimeType="application/sl" /> 
    </intent-filter> 

Et cette classe, utilisé en tant que service de mes Xamarin.Forms pcl

public class ShareDroid : IShare 
{ 
    private Context _context; 
    private FileSystemExDroid _fsDroid; 

    public ShareDroid() 
    { 
     _context = Android.App.Application.Context; 
     _fsDroid = new FileSystemExDroid(); 
    } 

    public void Show(string title, string message, string filePath) 
    { 
     if(!_fsDroid.FileExists(filePath)) 
      return; 

     var extension = filePath.Substring(filePath.LastIndexOf(".", StringComparison.Ordinal) + 1).ToLower(); 
     var contentType = GetContentType(extension); 

     var intent = new Intent(Intent.ActionSend); 
     intent.SetType(contentType); 
     intent.PutExtra(Intent.ExtraStream, Uri.Parse("file://" + filePath)); 
     intent.PutExtra(Intent.ExtraText, string.Empty); 
     intent.PutExtra(Intent.ExtraSubject, message ?? string.Empty); 

     var chooserIntent = Intent.CreateChooser(intent, title ?? string.Empty); 
     chooserIntent.SetFlags(ActivityFlags.ClearTop); 
     chooserIntent.SetFlags(ActivityFlags.NewTask); 
     _context.StartActivity(chooserIntent); 
    } 

    private static string GetContentType(string extension) 
    { 
     string contentType; 

     switch (extension) 
     { 
      case "pdf": 
       contentType = "application/pdf"; 
       break; 
      case "png": 
       contentType = "image/png"; 
       break; 
      case "sl": 
       contentType = "application/sl"; 
       break; 
      default: 
       contentType = "application/octet-stream"; 
       break; 
     } 

     return contentType; 
    } 
} 

Et ici j'appelle le spectacle méthode de mon service d'actions

private void OnShare() 
{ 
    var fileSystem = DependencyService.Get<IFileSystemEx>(); 
    var serializer = DependencyService.Get<ISerializer>(); 
    var share = DependencyService.Get<IShare>(); 
    var fileName = $"{Name}_{Id}.sl"; 
    var path = fileSystem.CreateFilePath(fileName, SpecialFolder.Personal); 
    serializer.Save(path, Model); 
    share.Show(Resources.ShareViaLabel, Resources.ShareViaMessage, path); 
} 

Quand je teste l'application sur n'importe quel appareil (pas émulé) je reçois le même résultat.

  • Gmail dit « Autorisation refusée pour la fixation »
  • WhatsApp et Telegram dit « L'attachement non supporté »

Le Resources.ShareViaMessage (ce qui est une petite description) est imprimé dans l'application cible sans problème.

Le fichier personnalisé est en fait un fichier .txt avec une extension personnalisée (.sl).

Quelqu'un peut-il aider?

+0

'Gmail' et' WhatsApp' doivent avoir certains contrôles de sécurité par leurs côtés, ce n'est pas modifiable du côté de votre application. –

+0

Je suppose qu'il doit y avoir un moyen de contourner ces contrôles (ou même certains 'si je peux hardcode pour éviter ces contrôles). Par exemple, de télégramme je peux partager n'importe quel type de fichier à whatsApp et viceversa (même avec gmail) ... – Easly

+0

Ainsi, j'ai essayé d'employer un .txt au lieu de mon dossier de .sl (le contenu du dossier est la même chose) et cela fonctionne sans problème. Alors, des conseils sur la façon d'enregistrer mon fichier .sl en tant que fichier texte/type mime simple? – Easly

Répondre

0

Finalement, j'ai trouvé une solution. j'ai enlevé les intentions du manifeste, et les coder dans l'activité principale comme ceci:

[IntentFilter(
new[] { Intent.ActionView }, 
Categories = new [] { Intent.CategoryBrowsable, Intent.CategoryDefault }, 
DataMimeType = "text/plain", 
DataPathPatterns = new [] 
{ 
    @".*\\.sl", 
    @".*\\..*\\.sl", 
    @".*\\..*\\..*\\.sl", 
    @".*\\..*\\..*\\..*\\.sl" 
})] 
[IntentFilter(
new[] { Intent.ActionSend }, 
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, 
DataMimeType = "text/plain", 
DataPathPatterns = new [] 
{ 
    @".*\\.sl", 
    @".*\\..*\\.sl", 
    @".*\\..*\\..*\\.sl", 
    @".*\\..*\\..*\\..*\\.sl" 
})] 

a également changé la méthode Share.Show utiliser le uri du fileprovider:

public void Show(string title, string filePath) 
    { 
     if(!_fsDroid.FileExists(filePath)) 
      return; 

     var fileUri = FileProvider.GetUriForFile(_context, "com.***********.******.fileprovider", new File(filePath)); 
     var intent = new Intent(Intent.ActionSend); 
     intent.SetType("text/plain"); 
     intent.PutExtra(Intent.ExtraText, string.Empty); 
     intent.PutExtra(Intent.ExtraStream, fileUri); 
     intent.SetData(fileUri); 
     intent.SetFlags(ActivityFlags.GrantReadUriPermission); 
     intent.SetFlags(ActivityFlags.ClearTop); 
     intent.SetFlags(ActivityFlags.NewTask); 

     var chooserIntent = Intent.CreateChooser(intent, title ?? string.Empty); 
     _context.StartActivity(chooserIntent); 
    } 

dans le manifeste, dans la balise d'application i ajouté

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

et c'est le contenu de mon file_paths.xml

<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <files-path name="exports" path="exports/"/> 
</paths> 

Et maintenant mon dossier des exportations d'application et WhatsApp, télégramme, gmail et toute autre application qui prennent en charge le fichier texte/ordinaire accepte les pièces jointes.

En outre, lors de l'ouverture/envoi du fichier .sl mon application est répertoriée et utilisable par défaut pour ce type de fichier.

Hope this helps à quelqu'un d'autre dans le futur :)