Xamarin android将图片上传到蔚蓝斑点的最佳方法?

时间:2018-07-17 16:39:20

标签: c# azure xamarin xamarin.android azure-storage

我已经尝试了一些尝试,但都没有成功。最新的香港专业教育学院试图使用一些可以在我的桌面上运行并给出图像真实路径的代码,但是当在Xamarin和我的android设备上将相同的路径传递给同一方法时,所选图像不会被上传,并且在那里没错。

任何人都知道问题可能是什么(错误的文件路径或完全其他的东西),或者有其他方法可以执行此任务?

这是相关的代码,上半部分仅在我的Xamarin项目中使用,并且我知道下半部分在通过手动传递的路径在桌面上运行时可以使用。

//这部分处理从电话获取图像及其数据,但是图像的路径似乎与我手动浏览至文件时不同。

    private void BtnClickFindImage(object sender, EventArgs e)
    {
        Intent = new Intent();
        Intent.SetType("image/*");
        Intent.SetAction(Intent.ActionGetContent);
        StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), PickImageId);
    }
    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        if ((requestCode == PickImageId) && (resultCode == Result.Ok) && (data != null))
        {
            Android.Net.Uri uri = data.Data;
            recipeImagePreview.SetImageURI(uri);

            var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
            var fullPath = Path.Combine(path.ToString(), "IMG_20180701_105406608.jpg");
            Manager_AzureServer_RecipeImages.PushFilTilWebsite(fullPath);
        }
    }

//这部分将文件推送到我的Azure存储单元,从我的桌面运行时,它就像一个超级按钮,但是在我的android设备上运行时,没有文件上传。要么路径不起作用,代码由于某种原因在android上不起作用,或者甚至可能存在某种android规则,默认情况下不允许从设备上传图片

        public static void PushFilTilWebsite(string _imagePath)
    {       
        ProcessAsync(_imagePath);
    }

    private static async Task ProcessAsync(string _imagePath)
    {
        CloudStorageAccount storageAccount = null;
        CloudBlobContainer cloudBlobContainer = null;

        // Retrieve the connection string for use with the application. The storage connection string is stored
        // in an environment variable on the machine running the application called storageconnectionstring.
        // If the environment variable is created after the application is launched in a console or with Visual
        // Studio, the shell needs to be closed and reloaded to take the environment variable into account.
        // Encrypt den her før release.
        string storageConnectionString = "XXX";

        // Check whether the connection string can be parsed.
        if (CloudStorageAccount.TryParse(storageConnectionString, out storageAccount))
        {
            try
            {
                // Create the CloudBlobClient that represents the Blob storage endpoint for the storage account.
                CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();

                // Create a container called 'quickstartblobs' and append a GUID value to it to make the name unique. 
                //cloudBlobContainer = cloudBlobClient.GetContainerReference("quickstartblobs" + Guid.NewGuid().ToString());
                cloudBlobContainer = cloudBlobClient.GetContainerReference("lghrecipeimages");

                // Set the permissions so the blobs are public. 
                BlobContainerPermissions permissions = new BlobContainerPermissions
                {
                    PublicAccess = BlobContainerPublicAccessType.Blob
                };
                await cloudBlobContainer.SetPermissionsAsync(permissions);

                // Get a reference to the blob address, then upload the file to the blob.
                // Use the value of localFileName for the blob name.
                CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference("test image upload2");
                await cloudBlockBlob.UploadFromFileAsync(_imagePath);

                finishedPushingToServer = true;                
            }
            catch (StorageException ex)
            {
                Console.WriteLine("Error returned from the service: {0}", ex.Message);
            }
            finally
            {
            }
        }
        else
        {
        }
        string test = "";
    }

2 个答案:

答案 0 :(得分:0)

问题是您没有使用正确的图像路径。

您从文件选择器意图中获得了Uri,但是除了预览之外,您不使用它。该Uri需要转换为外部存储中的实际路径。

private string GetFilePathFromUri(Android.Net.Uri uri)
{
    string[] column = { MediaStore.Images.ImageColumns.Data };

    var cursorLoader = new CursorLoader(this, uri, column, null, null, null);
    ICursor cursor = cursorLoader.LoadInBackground() as ICursor;

    string filePath = null;

    if (cursor != null)
    {
        var columnIndex = cursor.GetColumnIndexOrThrow(MediaStore.Images.ImageColumns.Data);
        cursor.MoveToFirst();
        filePath = cursor.GetString(columnIndex);
    }

    return filePath;
}

这会将您的Uri(看起来像content://media/images/external/1234)转换为文件路径,看起来像:/storage/emulated/0/DCIM/Camera/IMG_20180718_071002.jpg

此文件路径可以移交给Azure存储SDK进行上传。

答案 1 :(得分:0)

感谢Cheesebaron为我指出正确的方向,现在我可以正常工作了! 问题是我缺少使用设备上的外部存储所需的权限。在即时贴下面发布了为我修复的代码,简要说明:如果应用没有使用外部存储的权限,请提示此许可请求,一旦用户接受,便可以使用外部存储。

随时使用下面的工作代码,加油!

       private void BtnClickFindImage(object sender, EventArgs e)
    {
        if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == (int)Permission.Granted)
        {
            Toast.MakeText(this, "We already have this permission!", ToastLength.Short).Show();
        }
        else
        {  
            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.SetTitle("Permission needed!");
            alert.SetMessage("The pplication need special permission to continue");
            alert.SetPositiveButton("Request permission", (senderAlert, args) =>
            {
                RequestPermissions(PermissionsGroupLocation, RequestReadExternalStorageId);
            });

            alert.SetNegativeButton("Cancel", (senderAlert, args) =>
            {
                Toast.MakeText(this, "Cancelled!", ToastLength.Short).Show();
            });

            Dialog dialog = alert.Create();
            dialog.Show();

            return;
        }

        Intent = new Intent();
        Intent.SetType("image/*");
        Intent.SetAction(Intent.ActionGetContent);
        StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), PickImageId);
    }

    #region RuntimePermissions

    async Task TryToGetPermissions()
    {
        if ((int)Build.VERSION.SdkInt >= 23) // Android 7.0 - API 24 er min mobil
        {
            await GetPermissionsAsync();
            return;
        }
    }
    const int RequestReadExternalStorageId = 0;

    readonly string[] PermissionsGroupLocation =
        {
                        //TODO add more permissions
                        Manifest.Permission.ReadExternalStorage,
         };
    async Task GetPermissionsAsync()
    {
        const string permission = Manifest.Permission.ReadExternalStorage;

        if (CheckSelfPermission(permission) == (int)Android.Content.PM.Permission.Granted)
        {
            //TODO change the message to show the permissions name
            Toast.MakeText(this, "Special permissions granted", ToastLength.Short).Show();
            return;
        }

        if (ShouldShowRequestPermissionRationale(permission))
        {
            //set alert for executing the task
            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.SetTitle("Permissions Needed");
            alert.SetMessage("The application need special permissions to continue");
            alert.SetPositiveButton("Request Permissions", (senderAlert, args) =>
            {
                RequestPermissions(PermissionsGroupLocation, RequestReadExternalStorageId);
            });

            alert.SetNegativeButton("Cancel", (senderAlert, args) =>
            {
                Toast.MakeText(this, "Cancelled!", ToastLength.Short).Show();
            });

            Dialog dialog = alert.Create();
            dialog.Show();


            return;
        }

        RequestPermissions(PermissionsGroupLocation, RequestReadExternalStorageId);

    }
    public override async void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        switch (requestCode)
        {
            case RequestReadExternalStorageId:
                {
                    if (grantResults[0] == (int)Android.Content.PM.Permission.Granted)
                    {
                        Toast.MakeText(this, "Special permissions granted", ToastLength.Short).Show();

                    }
                    else
                    {
                        //Permission Denied :(
                        Toast.MakeText(this, "Special permissions denied", ToastLength.Short).Show();

                    }
                }
                break;
        }
        //base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }