Building Apps with Content Sharing

在使用 Android 应用程序的过程中,各应用之间难免会有数据交互。Android 应用框架的开发者也考虑到了这些,他们在 Android 中内置三种数据传输的方式:Intent,Content Provider,NFC。

上面的三种数据传输方式分别对应了不同场景下的数据交互:

  1. Intent

    应用程序内部或者应用程序之间文本类数据

  2. Content Provider

    应用程序之间大文件

  3. NFC

    不同设备之间大文件

一、Intent 使用详解

1.创建 Intent(发送端):

Intent intent = new Intent();

2.设置 Intent(发送端):

intent.setAction(Intent.SEND);
intent.setType("text/plain");(非必需)
intent.putExtra("KEY", "MSG");

3.发送 Intent(发送端):

扫描二维码关注公众号,回复: 2738788 查看本文章
startActivity(intent);
或 startActivityForResult(intent);

4.接受 Intent(接收端):

Intent intent = getIntent();

5.处理 Intent(接收端):

String action = intent.getAction();
String type = intent.getType();

if (Intent.ACTION_SEND.equals(action) && type != null) {
    if ("text/plain".equals(type)) {

            handleSendText(intent); // Handle text being sent

        } else if (type.startsWith("image/")) {

            handleSendImage(intent); // Handle single image being sent

        }
    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
        if (type.startsWith("image/")) {

            handleSendMultipleImages(intent); // Handle multiple images being sent

        }
    } else {

        // Handle other intents, such as being started from the home screen

}

6.返回 Intent(如果需要)(接收端):

Intent intent = new Intent();
intent.putXXX();
setResult(Activity.RESULT_OK, intent);
finish();

7.处理接收端返回的数据(如果需要)(发送端):

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode == RESULT_OK){
            switch(requestCode){
                case CommonConstant.REQUEST_CODE_1:

                    // parse the feedback data--intent

                    break;
            }
        }
    }

二、Content Provider 使用详解

此处主要涉及到应用程序之间文件类数据分享,因此,此处主要讲解的是 Content Provider 的子类——File Provider。

1.配置要分享服务端清单文件(服务端):

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

2.配置目标分享文件的路径(服务端):

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_texts" path="texts/"/>
    <files-path name="my_images" path="images/"/>
    <files-path name="my_des_dir" path="des_dir/"/>
    <external-path name="my_capturing_photos" path="Android/data/com.smart.develop/files/Pictures" />
</paths>

3.接受客户端请求(服务端):

<activity
    android:name=".content_sharing.sharing_files.FileSelectActivity"
    android:label="@string/file_select">
    <intent-filter>
        <action android:name="android.intent.action.PICK" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.OPENABLE" />

        <data android:mimeType="text/plain" />
        <data android:mimeType="image/*" />
        <data android:mimeType="smart/*" />
    </intent-filter>
</activity>

---

public class FileSelectActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    private ListView mLV;
    private File mPrivateRootDir;
    private File mDesDir;
    private File mDesTextFile, mDesImageFile;
    private String[] mDesFilesName;
    private File[] mDesFiles;
    private ArrayAdapter<String> mAdapter;
    private Uri mFileUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
    }

    private void initView() {
        mLV = (ListView) findViewById(R.id.lv);
        mLV.setOnItemClickListener(this);
    }

    private void initData() {
        mPrivateRootDir = getFilesDir();
        mDesDir = new File(mPrivateRootDir, "des_dir");
        if (!mDesDir.exists()) {
            mDesDir.mkdir();
        }
        mDesTextFile = new File(mDesDir, "des_text.txt");
        mDesImageFile = new File(mDesDir, "des_image.png");
        try {
            if (!mDesTextFile.exists()) {
                mDesTextFile.createNewFile();
                mDesImageFile.createNewFile();
            }

            AssetManager am = getAssets();
            InputStream is = am.open("des_text_file");
            FileOutputStream textFOS = new FileOutputStream(mDesTextFile);
            byte[] bytes = new byte[1024];
            int temp = 0;
            while ((temp = is.read(bytes)) != -1) {
                textFOS.write(bytes, 0, temp);
            }
            textFOS.flush();
            textFOS.close();

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dancing);
            FileOutputStream imageFOS = new FileOutputStream(mDesImageFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, imageFOS);
            imageFOS.flush();
            imageFOS.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        mDesFilesName = mDesDir.list();
        mDesFiles = mDesDir.listFiles();
        mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDesFilesName);
        mLV.setAdapter(mAdapter);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        try {
            mFileUri = FileProvider.getUriForFile(this, "com.example.deep_practice.fileprovider", mDesFiles[position]);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        if (mFileUri != null) {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(mFileUri, getContentResolver().getType(mFileUri));
            // Set the result
            this.setResult(Activity.RESULT_OK, intent);
            this.finish();
        }
    }

}

4.返回数据(服务段):

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(mFileUri, getContentResolver().getType(mFileUri));
// set the result
this.setResult(Activity.RESULT_OK, intent);
this.finish();

5.发送请求(客户端):

Intent requestFileIntent = new Intent(Intent.ACTION_PICK);
//        requestFileIntent.setType("text/plain");
//        requestFileIntent.setType("image/*");
//此处的 Type 是可以自定义的,只要在目标组建的 <data android:mimeType="smart/*"/> 声明相同的类型即可
//既然 Type 可以自定义,那么其他的可以自定吗?例如 Action
requestFileIntent.setType("smart/*");
startActivityForResult(requestFileIntent, CommonConstant.REQUEST_CODE_1);

6.处理返回结果(客户端):

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent returnIntent) {
    super.onActivityResult(requestCode, resultCode, returnIntent);
    if (CommonConstant.REQUEST_CODE_1 == requestCode){
        if (RESULT_OK == resultCode){

            Uri returnUri = returnIntent.getData();
            ContentResolver contentResolver = getContentResolver();
            Cursor returnCursor = contentResolver.query(returnUri, null, null, null, null);
            int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
            int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
            returnCursor.moveToFirst();
            mDesName.setText(returnCursor.getString(nameIndex));
            mDesSize.setText((Float.toString(returnCursor.getLong(sizeIndex)/1024/1024f)) + "M");
            String mimeType = contentResolver.getType(returnUri);
            mDesType.setText(mimeType);
            try {
                ParcelFileDescriptor inputPFD = contentResolver.openFileDescriptor(returnUri, "r");
                FileDescriptor fd = inputPFD.getFileDescriptor();
                if(mimeType.equals("text/plain")){
                    FileInputStream fis = new FileInputStream(fd);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                    }
                    fis.close();
                    mDesContent.setText(sb.toString());
                }else if (mimeType.equals("image/png")){
                    Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
                    mDesIV.setImageBitmap(bitmap);
                }
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
        }
    }
}

三、NFC 使用详解

完成上面两个之后,我相信很多都大致明白怎么做了,首先搞清楚哪个是客户端,哪个是服务端,当你搞清楚了二者,你也就知道怎么做了。由于我的机子不支持 NFC 功能,所以只是测试了下当前设备是否支持 NFC,虽然没做,但是大致的流程是不变的:

1.配置权限并检查当前设备是否支持 NFC(发送端 & 服务端):

//所需权限
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

//所需特性
<uses-feature
    android:name="android.hardware.nfc"
    android:required="true" />

//检查当前设备是否支持 NFC
PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)

2.检查当前设备的 Android 版本是否大于 16(发送端 & 服务端):

Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1

3.发送文件(发送端):

//send file

4.接收文件(接收端):

//receive file

心得:合理地将问题拆解,才是解决问题的最佳办法。

猜你喜欢

转载自blog.csdn.net/zjh_1110120/article/details/72775901