tus / tus-android-client

The tus client for Android.
https://tus.io/
161 stars 46 forks source link

FileNotFoundException on android 5.0,the cursor always be null in the TusAndroidUpload constructor #31

Closed softboy99 closed 4 years ago

softboy99 commented 5 years ago

I get the file uri from the os camera in "OnActivityResult"

Acconut commented 5 years ago

Please provide more details, such as your code responsible for handling tus and exact steps to reproduce this issue.

softboy99 commented 5 years ago
public class MainActivity extends AppCompatActivity {
    private static final int CAMERA_REQUEST_CODE = 2;
    @BindView(R.id.etBarcode)
    EditText etBarcode;
    @BindView(R.id.tvStatus)
    TextView tvStatus;
    @BindView(R.id.progressBar)
    ProgressBar progressBar;
    private TusClient client;
    private UploadTask uploadTask;
    private File tempFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        try {
            SharedPreferences pref = getSharedPreferences("tus", 0);
            client = new TusClient();
            client.setUploadCreationURL(new URL(BuildConfig.API_BASE_URL + "upload"));
            client.enableResuming(new TusPreferencesURLStore(pref));
        } catch(Exception e) {
            showError(e);
        }
    }

    public void btnCapture_Click(View view){
        File fDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss");
        String[] sArr = sdf.format(d).split(" ");
        String f = "IMG_" + sArr[0] + "_" + sArr[1] + ".jpg";
        tempFile = new File(fDir, f);
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //判断版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {   //如果在Android7.0以上,使用FileProvider获取Uri
            intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(MainActivity.this, "com.ilab.iphoto", tempFile);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
        } else {    //否则使用Uri.fromFile(file)方法获取Uri
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
        }
        startActivityForResult(intent, CAMERA_REQUEST_CODE);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case CAMERA_REQUEST_CODE:
                    Uri fileUri =null;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        fileUri = FileProvider.getUriForFile(MainActivity.this, "com.ilab.iphoto", tempFile);
                    } else {
                        fileUri = Uri.fromFile(tempFile);
                    }
                    String barcode = etBarcode.getText().toString().trim();
                    try {
                        TusUpload upload = new TusAndroidUpload(fileUri, this);
                        uploadTask = new UploadTask(this, client, upload);
                        uploadTask.execute(new Void[0]);
                    } catch (Exception e) {
                        showError(e);
                    }
                    break;
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void setStatus(String s) {
        tvStatus.setText(s);
    }

    private void setUploadProgress(int progress) {
        progressBar.setProgress(progress);
    }

    private void showError(Exception e) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("内部错误");
        builder.setMessage(e.getMessage());
        AlertDialog dialog = builder.create();
        dialog.show();
        e.printStackTrace();
    }

    private class UploadTask extends AsyncTask<Void, Long, URL> {
        private MainActivity activity;
        private TusClient client;
        private TusUpload upload;
        private Exception exception;

        public UploadTask(MainActivity activity, TusClient client, TusUpload upload) {
            this.activity = activity;
            this.client = client;
            this.upload = upload;
        }

        @Override
        protected void onPreExecute() {
            activity.setStatus("");
            activity.setUploadProgress(0);
        }

        @Override
        protected void onPostExecute(URL uploadURL) {
            activity.setStatus("上传完成!\n" + uploadURL.toString());
        }

        @Override
        protected void onCancelled() {
            if(exception != null) {
                activity.showError(exception);
            }
        }

        @Override
        protected void onProgressUpdate(Long... updates) {
            long uploadedBytes = updates[0];
            long totalBytes = updates[1];
            activity.setStatus(String.format("Uploaded %d/%d.", uploadedBytes, totalBytes));
            activity.setUploadProgress((int) ((double) uploadedBytes * 100 / totalBytes));
        }

        @Override
        protected URL doInBackground(Void... params) {
            try {
                TusUploader uploader = client.resumeOrCreateUpload(upload);
                long totalBytes = upload.getSize();
                long uploadedBytes = uploader.getOffset();
                // Upload file in 1MiB chunks
                uploader.setChunkSize(1024 * 1024);
                while(!isCancelled() && uploader.uploadChunk() > 0) {
                    uploadedBytes = uploader.getOffset();
                    publishProgress(uploadedBytes, totalBytes);
                }
                uploader.finish();
                return uploader.getUploadURL();
            } catch(Exception e) {
                exception = e;
                cancel(true);
            }
            return null;
        }
    }
}
softboy99 commented 5 years ago

@Acconut , Is it enough?

Acconut commented 5 years ago

I don't see any obvious error in your code but I am not an Android expert and I have never used the camera directly, so that's kind of out of my scope. It will take some time until I have time to set up my local development environment again and try it out on my own, at least two weeks.

In the meantime, you might be able to debug this on your own. Does this error only occur on Android 5.0 or also other versions? You can also try to bypass TusAndroidUpload and use TusUpload directly: https://tus.github.io/tus-java-client/javadoc/io/tus/java/client/TusUpload.html. Just use the empty constructor and set the inputstream, size etc properties.

Acconut commented 4 years ago

Closing this issue due to inactivity. Feel free to leave a comment if you want to continue the discussion :)