2016-06-30 2 views
0

Я использую MvvmCross на Android через Xamarin, и у меня возникла проблема. Я создал основной сервисный интерфейс под названием IFileExplorerService.Как подождать OnActivityResult в Xamarin C# на Android

Цель этого интерфейса - открыть диалоговое окно открытого файла и выбрать файл, независимо от того, какое устройство (Windows или Android).

На андроиде я легко справился с этим без моего интерфейса через просмотр, просто используя OnActivityResult и намерения.

Но я просто не могу заставить его работать с моего представления, так как реализация интерфейса является одиночной кнопкой, зарегистрированной в настройке, когда я вызываю ее из своей модели просмотра, абсолютно никто не обрабатывает OnActivityResult.

Я попытался сделать свой имплантат FileExplorer наследованием от Activity или MvxActivity, так как мой FileExplorer может переопределить OnActivityResult, но это не удается.

Я попытался использовать StartActivity (typeof (FileExplorer)), но это, очевидно, потерпит неудачу в любом случае, так как это не будет singleton, зарегистрированный в MvvmCross, который будет запущен.

Есть ли у кого-нибудь идеи/комментарий/вопрос/предложение, чтобы помочь мне в этом?

Вот мой код до сих пор:

public class FileExplorerService : IFileExplorerServiceMock 
    { 
     string _addedFileName; 
     public static int REQUEST_FILE_CAPTURE = 2; 
     private bool _hasMediaBeenAdded; 
     private TaskCompletionSource<String> GetFileTask; 
     public Activity activity; 
     public FileExplorerService() 
     { 
      GetFileTask = new TaskCompletionSource<string>(); 
     } 


     private void DispatchSelectFileIntent() 
     { 
      Intent Intent = new Intent(); 
      Intent.SetType("*/*"); 
      Intent.SetAction(Intent.ActionGetContent); 

      activity.StartActivityForResult(Intent.CreateChooser(Intent, "Select File"), REQUEST_FILE_CAPTURE); 
     } 

     public void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data) 
     { 
      // 
      if (resultCode == Result.Ok) 
      { 
       if (data != null) 
       { 

        bool isFileCopied = CopySelectedFileToAddedFilesDirectory(data.Data); 
        if (isFileCopied) 
        { 
         //everything went well 
         ShowSuccesAlertDialog(); 
         GetFileTask.SetResult(_addedFileName); 
        } 
        else 
        { 
         ShowFailureAlertDialog(); 
         //oops something crashed 
         //Log 
        } 
       } 
      } 
      else 
      { 
       _addedFileName = String.Empty; 
      }    
     } 

     private void ShowFailureAlertDialog() 
     { 
      AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
      AlertDialog alertDialog = builder.Create(); 
      alertDialog.SetTitle("Oops... something went wrong"); 
      alertDialog.SetIcon(Android.Resource.Drawable.IcDialogAlert); 
      alertDialog.SetMessage("Something went rong when adding a media"); 
      alertDialog.SetButton("Ok", (s, ev) => 
      { 

      }); 
      alertDialog.Show(); 
     } 

     private void ShowSuccesAlertDialog() 
     { 
      AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
      AlertDialog alertDialog = builder.Create(); 
      alertDialog.SetTitle("Media added with succes !"); 
      alertDialog.SetIcon(Android.Resource.Drawable.IcDialogAlert); 
      alertDialog.SetMessage("Your media has been added with succes"); 
      alertDialog.SetButton("Ok", (s, ev) => 
      { 
       _hasMediaBeenAdded = true; 


      }); 
      alertDialog.Show(); 
     } 
     private void DeletePreviousAddedFile() 
     { 
      //todo delete file only if selected rex type is the same 
      if (_hasMediaBeenAdded) 
      { 
       MsFile.Delete(_addedFileName); 
       _addedFileName = string.Empty; 
       _hasMediaBeenAdded = false; 
      } 
     } 

     private static string GetRealPathFromURI(Context _context, Android.Net.Uri contentUri) 
     { 
      string[] projection = new string[] { MediaStore.MediaColumns.Data }; 
      ContentResolver cr = _context.ContentResolver; 
      Android.Database.ICursor cursor = cr.Query(contentUri, projection, null, null, null); 
      if (cursor != null && cursor.Count > 0) 
      { 
       cursor.MoveToFirst(); 
       int index = cursor.GetColumnIndex(Android.Provider.MediaStore.MediaColumns.Data); 
       return cursor.GetString(index); 
      } 
      return ""; 
     } 
     private bool CopySelectedFileToAddedFilesDirectory(Android.Net.Uri data) 
     { 
      var dir = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Medias/AddedMedias/Files/"); 

      if (!dir.Exists()) 
       dir.Mkdirs(); 
      string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Medias/AddedMedias/Files/"; 
      JavaFile file = new Java.IO.File(path); 

      string realPath = GetRealPathFromURI(activity.ApplicationContext, data); 
      string FileName = realPath.Split('/').Last(); 
      _addedFileName = Path.Combine(dir + "/" + FileName); 
      if (!string.IsNullOrEmpty(realPath)) 
      { 
       //todo manage errors 
       using (FileStream fs = new FileStream(realPath, FileMode.Open)) 
       { 
        byte[] datas = new byte[fs.Length]; 
        int numberBytesToRead = (int)fs.Length; 
        int numBytesRead = 0; 
        while (numberBytesToRead > 0) 
        { 
         int n = fs.Read(datas, numBytesRead, numberBytesToRead); 

         if (n == 0) 
         { 
          break; 
         } 
         numBytesRead += n; 
         numberBytesToRead -= n; 
        } 
        using (FileStream fs2 = System.IO.File.OpenWrite(Path.Combine(dir + "/" + FileName))) 
        { 
         fs2.Write(datas, 0, datas.Length); 
        } 
       } 
       return true; 
      } 
      return false; 
     } 


     public List<FileType> FileTypes 
     { 
      get 
      { 
       return new List<FileType>(); 
      } 
     } 

     public async Task<string> Show(string fiel) 
     { 
      if (activity != null) 
      { 
       DeletePreviousAddedFile(); 
       DispatchSelectFileIntent(); 

       return GetFileTask.Task.Result; 
      } 
      else 
      { 
       return String.Empty; 
      } 

}

И на мой взгляд:

protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 
      SetContentView(Resource.Layout.RexView); 
      _addMediaController = new AddMediaController(this, (RexViewModel)base.ViewModel); 
      _flyoutMenuAnimator = new FlyoutMenuAnimator(this); 

      var t= Mvx.Resolve<IFileExplorerServiceMock>() as FileExplorerService; 
      t.activity = this; 

     } 
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) 
     { 
      var t = Mvx.Resolve<IFileExplorerServiceMock>() as FileExplorerService; 
      t.OnActivityResult(requestCode, resultCode, data); 
      base.OnActivityResult(requestCode, resultCode, data); 
     } 

С этим все работы, кроме того OnActivityResult никогда не вызывается на мой взгляд

ответ

2

Хорошо, я решил! Благодаря этой ссылке https://forums.xamarin.com/discussion/45691/pass-data-from-android-project-to-pcl

Мне пришлось переписать начальную активность, чтобы дать ей обратный вызов в качестве аргумента, а обратный вызов - это мой OnActivityResult в моем проводнике файлов.

Вот мой код для тех, кто в ней нуждаются: в MyView:

private Action<int, Result, Intent> _resultCallback; 

     public void StartActivity(Intent intent,int resultCode, Action<int, Result, Intent> resultCallback) 
     { 
      _resultCallback = resultCallback; 

      StartActivityForResult(intent, resultCode); 
     } 

     protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) 
     { 
      base.OnActivityResult(requestCode, resultCode, data); 
      if (_resultCallback != null) 
      { 
       _resultCallback(requestCode, resultCode, data); 
       _resultCallback = null; 
      } 
     } 

и в моем Проводник:

string _addedFileName; 
     public static int REQUEST_FILE_CAPTURE = 2; 
     private bool _hasMediaBeenAdded; 
     private TaskCompletionSource<String> GetFileTask; 
     public RexView activity; 
     public FileExplorerService() 
     { 
     } 


     private void DispatchSelectFileIntent() 
     { 
      Intent intent = new Intent(); 
      intent.SetType("*/*"); 
      intent.SetAction(Intent.ActionGetContent); 

      GetFileTask = new TaskCompletionSource<string>(); 
      activity.StartActivity(Intent.CreateChooser(intent, "Select File"), REQUEST_FILE_CAPTURE, OnActivityResult); 
     // activity.StartActivityForResult(Intent.CreateChooser(intent, "Select File"), REQUEST_FILE_CAPTURE); 
     } 

     public void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data) 
     { 

      // 
      if (resultCode == Result.Ok) 
      { 
       if (data != null) 
       { 

        bool isFileCopied = CopySelectedFileToAddedFilesDirectory(data.Data); 
        if (isFileCopied) 
        { 
         //everything went well 
         ShowSuccesAlertDialog(); 
         GetFileTask.SetResult(_addedFileName); 
        } 
        else 
        { 
         ShowFailureAlertDialog(); 
         //oops something crashed 
         //Log 
        } 
       } 
      } 
      else 
      { 
       _addedFileName = String.Empty; 
      }    
     } 

     private void ShowFailureAlertDialog() 
     { 
      AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
      AlertDialog alertDialog = builder.Create(); 
      alertDialog.SetTitle("Oops... something went wrong"); 
      alertDialog.SetIcon(Android.Resource.Drawable.IcDialogAlert); 
      alertDialog.SetMessage("Something went rong when adding a media"); 
      alertDialog.SetButton("Ok", (s, ev) => 
      { 

      }); 
      alertDialog.Show(); 
     } 

     private void ShowSuccesAlertDialog() 
     { 
      AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
      AlertDialog alertDialog = builder.Create(); 
      alertDialog.SetTitle("Media added with succes !"); 
      alertDialog.SetIcon(Android.Resource.Drawable.IcDialogAlert); 
      alertDialog.SetMessage("Your media has been added with succes"); 
      alertDialog.SetButton("Ok", (s, ev) => 
      { 
       _hasMediaBeenAdded = true; 


      }); 
      alertDialog.Show(); 
     } 
     private void DeletePreviousAddedFile() 
     { 
      //todo delete file only if selected rex type is the same 
      if (_hasMediaBeenAdded) 
      { 
       MsFile.Delete(_addedFileName); 
       _addedFileName = string.Empty; 
       _hasMediaBeenAdded = false; 
      } 
     } 

     private static string GetRealPathFromURI(Context _context, Android.Net.Uri contentUri) 
     { 
      string[] projection = new string[] { MediaStore.MediaColumns.Data }; 
      ContentResolver cr = _context.ContentResolver; 
      Android.Database.ICursor cursor = cr.Query(contentUri, projection, null, null, null); 
      if (cursor != null && cursor.Count > 0) 
      { 
       cursor.MoveToFirst(); 
       int index = cursor.GetColumnIndex(Android.Provider.MediaStore.MediaColumns.Data); 
       return cursor.GetString(index); 
      } 
      return ""; 
     } 
     private bool CopySelectedFileToAddedFilesDirectory(Android.Net.Uri data) 
     { 
      var dir = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Medias/AddedMedias/Files/"); 

      if (!dir.Exists()) 
       dir.Mkdirs(); 
      string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Medias/AddedMedias/Files/"; 
      JavaFile file = new Java.IO.File(path); 

      string realPath = GetRealPathFromURI(activity.ApplicationContext, data); 
      string FileName = realPath.Split('/').Last(); 
      _addedFileName = Path.Combine(dir + "/" + FileName); 
      if (!string.IsNullOrEmpty(realPath)) 
      { 
       //todo manage errors 
       using (FileStream fs = new FileStream(realPath, FileMode.Open)) 
       { 
        byte[] datas = new byte[fs.Length]; 
        int numberBytesToRead = (int)fs.Length; 
        int numBytesRead = 0; 
        while (numberBytesToRead > 0) 
        { 
         int n = fs.Read(datas, numBytesRead, numberBytesToRead); 

         if (n == 0) 
         { 
          break; 
         } 
         numBytesRead += n; 
         numberBytesToRead -= n; 
        } 
        using (FileStream fs2 = System.IO.File.OpenWrite(Path.Combine(dir + "/" + FileName))) 
        { 
         fs2.Write(datas, 0, datas.Length); 
        } 
       } 
       return true; 
      } 
      return false; 
     } 


     public List<FileType> FileTypes 
     { 
      get 
      { 
       return new List<FileType>(); 
      } 
     } 

     public async Task<string> Show(string fiel) 
     { 
      if (activity != null) 
      { 
       DeletePreviousAddedFile(); 
       DispatchSelectFileIntent(); 

       return await GetFileTask.Task; 
      } 
      else 
      { 
       return String.Empty; 
      } 
     } 
    } 

И на мой взгляд, модель

private async void BrowseMedias() 
     { 
      var fileExplorerService = Mvx.Resolve<IFileExplorerServiceMock>(); 
      fileExplorerService.FileTypes.Add(FileType.Picture); 
      string fileSavedPath = await fileExplorerService.Show(DatabaseContentPath); 
      /* file managment*/ 
     }