Android intent filter: associate app with file extension

后端 未结 16 2121
北海茫月
北海茫月 2020-11-22 11:06

I have a custom file type/extension that I want to associate my app with.

As far as I know, the data element is made for this purpose, but I can\'t get it working. h

16条回答
  •  我在风中等你
    2020-11-22 11:56

    My findings:

    You need several filters to deal with the different ways of retrieving a file. ie, by gmail attachment, by file explorer, by HTTP, by FTP... They all send very different intents.

    And you need to filter out the intent that trigger your activity in your activity code.

    For the example below, I created a fake file type new.mrz. And I retrieved it from gmail attachment and file explorer.

    Activity code added in the onCreate():

            Intent intent = getIntent();
            String action = intent.getAction();
    
            if (action.compareTo(Intent.ACTION_VIEW) == 0) {
                String scheme = intent.getScheme();
                ContentResolver resolver = getContentResolver();
    
                if (scheme.compareTo(ContentResolver.SCHEME_CONTENT) == 0) {
                    Uri uri = intent.getData();
                    String name = getContentName(resolver, uri);
    
                    Log.v("tag" , "Content intent detected: " + action + " : " + intent.getDataString() + " : " + intent.getType() + " : " + name);
                    InputStream input = resolver.openInputStream(uri);
                    String importfilepath = "/sdcard/My Documents/" + name; 
                    InputStreamToFile(input, importfilepath);
                }
                else if (scheme.compareTo(ContentResolver.SCHEME_FILE) == 0) {
                    Uri uri = intent.getData();
                    String name = uri.getLastPathSegment();
    
                    Log.v("tag" , "File intent detected: " + action + " : " + intent.getDataString() + " : " + intent.getType() + " : " + name);
                    InputStream input = resolver.openInputStream(uri);
                    String importfilepath = "/sdcard/My Documents/" + name; 
                    InputStreamToFile(input, importfilepath);
                }
                else if (scheme.compareTo("http") == 0) {
                    // TODO Import from HTTP!
                }
                else if (scheme.compareTo("ftp") == 0) {
                    // TODO Import from FTP!
                }
            }
    

    Gmail attachement filter:

            
                
                
                
                
            
    
    • LOG: Content intent detected: android.intent.action.VIEW : content://gmail-ls/l.foul@gmail.com/messages/2950/attachments/0.1/BEST/false : application/octet-stream : new.mrz

    File explorer filter:

            
                
                
                
                
            
    
    • LOG: File intent detected: android.intent.action.VIEW : file:///storage/sdcard0/My%20Documents/new.mrz : null : new.mrz

    HTTP filter:

            
                
                
                
                
            
    

    Private functions used above:

    private String getContentName(ContentResolver resolver, Uri uri){
        Cursor cursor = resolver.query(uri, null, null, null, null);
        cursor.moveToFirst();
        int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
        if (nameIndex >= 0) {
            return cursor.getString(nameIndex);
        } else {
            return null;
        }
    }
    
    private void InputStreamToFile(InputStream in, String file) {
        try {
            OutputStream out = new FileOutputStream(new File(file));
    
            int size = 0;
            byte[] buffer = new byte[1024];
    
            while ((size = in.read(buffer)) != -1) {
                out.write(buffer, 0, size);
            }
    
            out.close();
        }
        catch (Exception e) {
            Log.e("MainActivity", "InputStreamToFile exception: " + e.getMessage());
        }
    }
    

提交回复
热议问题