Android 官网Train阅读记录——3

LZ阅读的是中文翻译版本:http://hukai.me/android-training-course-in-chinese/basics/activity-lifecycle/recreating.html,试验机系统版本7.1。

2、 Android分享操作

2.1 分享简单的数据

2.1.1 给其他App发送简单的数据

发送文本

Intent sendTextIntent = new Intent();
                sendTextIntent.setAction(Intent.ACTION_SEND);
                sendTextIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.text_for_send));
                sendTextIntent.setType("text/plain");
startActivity(Intent.createChooser(sendTextIntent, getResources().getText(R.string.open_web_with)));
发送二进制流数据

Intent sendTextIntent = new Intent();
                sendTextIntent.setAction(Intent.ACTION_SEND);
                File file = new File(Environment.getExternalStorageDirectory().toString() + "/photos/20170329165514.png");
                Uri image_uri = Uri.fromFile(file);
                sendTextIntent.putExtra(Intent.EXTRA_STREAM, image_uri);
                sendTextIntent.setType("image/jpeg");
                startActivity(Intent.createChooser(sendTextIntent, getResources().getText(R.string.open_web_with)));
一次发送多块内容

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));


2.1.2 接收从其他App发送的数据

首先在接收的Activity的清单文件中添加intent-filter,指明该Activity可以接收的文件类型,一个Activity可以有多个intent-filter。

<activity android:name=".ui.MyActivity" >
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>
然后再代码中处理接收到的数据即可

void onCreate (Bundle savedInstanceState) {
    ...
    // Get intent, action and MIME type
    Intent intent = getIntent();
    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
    }
    ...
}

void handleSendText(Intent intent) {
    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    if (sharedText != null) {
        // Update UI to reflect text being shared
    }
}

void handleSendImage(Intent intent) {
    Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
    if (imageUri != null) {
        // Update UI to reflect image being shared
    }
}

void handleSendMultipleImages(Intent intent) {
    ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    if (imageUris != null) {
        // Update UI to reflect multiple images being shared
    }
}


2.1.3 给ActionBar增加分享功能

这里要使用到ShareActionProvider。首先为相应的Activity定义一个menu文件,目录在res/menu下。例

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/menu_item_share"
        android:showAsAction="ifRoom"
        android:title="Share"
        app:actionProviderClass="android.support.v7.widget.ShareActionProvider" />
    ...
</menu>
注意上面代码中的app:actionProviderClass属性使用的是support.v7包中的ShareActionProvider,这是因为在高版本系统中使用的ActionBar都是用的support包中的,所以相应的ShareActionProvider也要使用support包中的,否则会出现什么效果也没有的情况。

接着在Activity中复写onCreateOptionsMenu方法

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_share, menu);
        MenuItem share = menu.findItem(R.id.action_share);
        ShareActionProvider mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(share);
        Intent sendTextIntent = new Intent();
        sendTextIntent.setAction(Intent.ACTION_SEND);
        sendTextIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.text_for_send));
        sendTextIntent.setType("text/plain");
        mShareActionProvider.setShareIntent(sendTextIntent);
        return true;
    }
关键的几步是,获取MenuItem,然后调用MenuItemCompat的getActionProvider来获得ShareActionProvider,当然,这个ShareActionProvider也是v7包中的,最后为其设置ShareIntent即可。这样App运行起来后,就可以在ActionBar的右侧看到一个常见的分享按钮,点击它,就出现一系列可以将指定内容分享到其中的App列表。


2.3 使用NFC分享文件

这里使用的是Android Beam功能近场传输文件。该功能只支持4.2及以上版本的系统。

在编写代码之前,首先得为应用添加NFC和WRITE_EXTERNAL_STORAGE权限。

 <uses-permission android:name="android.permission.NFC"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
同时,为了指定NFC功能,还要添加uses-feature

 <uses-feature
            android:name="android.hardware.nfc"
            android:required="false"/>
上面的权限和特色功能都添加以后,才可以进行接下来的编码。

首先是NFC发送文件。不过在此之前,先判断手机是否支持NFC功能

PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)
继续判断手机的系统版本是否等于或高于4.2

Build.VERSION.SDK_INT <
                Build.VERSION_CODES.JELLY_BEAN_MR1
若上面两项都满足,就可以进行具体的发送文件功能的实现

首先创建一个NfcAdapter对象,它就是用于执行具体传输的对象

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
接着需要创建一个提供文件的回调函数,它是供文件给NfcAdapter对象发送的,要实现NfcAdapter.CreateBeamUrisCallback回调接口。

public class MainActivity extends Activity {
    ...
    // List of URIs to provide to Android Beam
    private Uri[] mFileUris = new Uri[10];
    ...
    /**
     * Callback that Android Beam file transfer calls to get
     * files to share
     */
    private class FileUriCallback implements
            NfcAdapter.CreateBeamUrisCallback {
        public FileUriCallback() {
        }
        /**
         * Create content URIs as needed to share with another device
         */
        @Override
        public Uri[] createBeamUris(NfcEvent event) {
            return mFileUris;
        }
    }
    ...
}
接下来就是创建回调函数的对象并设置给NfcAdapter对象

mFileUriCallback = new FileUriCallback();
        // Set the dynamic callback for URI requests.
        mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this);
最后指定要发送的文件

 /*
     * Create a list of URIs, get a File,
     * and set its permissions
     */
    private Uri[] mFileUris = new Uri[10];
    String transferFile = "transferimage.jpg";
    File extDir = getExternalFilesDir(null);
    File requestFile = new File(extDir, transferFile);
    requestFile.setReadable(true, false);
    // Get a URI for the File and add it to the list of URIs
    fileUri = Uri.fromFile(requestFile);
    if (fileUri != null) {
        mFileUris[0] = fileUri;
    } else {
        Log.e("My Activity", "No File URI available for file.");
    }
这个文件的Uri数组,就是回调函数里返回的mFileUris数组。


2.3.2 接收其他设备的文件

当Android Beam文件传输将文件拷贝至接收设备后,它会fabulous一个包含intent的通知,该Intent拥有:ACTION_VIEW,首个被传输文件的MIME类型,以及一个指向第一个文件的URI。所以,要接收文件,就得在Activity的intent-filter中添加VIEW的action,同时还要添加默认的category和data。

<activity
        android:name="com.example.android.nfctransfer.ViewActivity"
        android:label="Android Beam Viewer" >
        ...
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            ...
        </intent-filter>
    </activity>
因为App可能接收到除了Android Beam文件传输之外的某个来源所发出的含有VIEW_ACTION的Intent,所以要检查Intent的Scheme和Authority。

下面就是具体的接收实例

public class MainActivity extends Activity {
    ...
    // A File object containing the path to the transferred files
    private File mParentPath;
    // Incoming Intent
    private Intent mIntent;
    ...
    /*
     * Called from onNewIntent() for a SINGLE_TOP Activity
     * or onCreate() for a new Activity. For onNewIntent(),
     * remember to call setIntent() to store the most
     * current Intent
     *
     */
    private void handleViewIntent() {
        ...
        // Get the Intent action
        mIntent = getIntent();
        String action = mIntent.getAction();
        /*
         * For ACTION_VIEW, the Activity is being asked to display data.
         * Get the URI.
         */
        if (TextUtils.equals(action, Intent.ACTION_VIEW)) {
            // Get the URI from the Intent
            Uri beamUri = mIntent.getData();
            /*
             * Test for the type of URI, by getting its scheme value
             */
            if (TextUtils.equals(beamUri.getScheme(), "file")) {
                mParentPath = handleFileUri(beamUri);
            } else if (TextUtils.equals(
                    beamUri.getScheme(), "content")) {
                mParentPath = handleContentUri(beamUri);
            }
        }
        ...
    }
    ...
}
 ...
    public String handleFileUri(Uri beamUri) {
        // Get the path part of the URI
        String fileName = beamUri.getPath();
        // Create a File object for this filename
        File copiedFile = new File(fileName);
        // Get a string containing the file's parent directory
        return copiedFile.getParent();
    }
    ...
 ...
    public String handleContentUri(Uri beamUri) {
        // Position of the filename in the query Cursor
        int filenameIndex;
        // File object for the filename
        File copiedFile;
        // The filename stored in MediaStore
        String fileName;
        // Test the authority of the URI
        if (!TextUtils.equals(beamUri.getAuthority(), MediaStore.AUTHORITY)) {
            /*
             * Handle content URIs for other content providers
             */
        // For a MediaStore content URI
        } else {
            // Get the column that contains the file name
            String[] projection = { MediaStore.MediaColumns.DATA };
            Cursor pathCursor =
                    getContentResolver().query(beamUri, projection,
                    null, null, null);
            // Check for a valid cursor
            if (pathCursor != null &&
                    pathCursor.moveToFirst()) {
                // Get the column index in the Cursor
                filenameIndex = pathCursor.getColumnIndex(
                        MediaStore.MediaColumns.DATA);
                // Get the full file name including path
                fileName = pathCursor.getString(filenameIndex);
                // Create a File object for the filename
                copiedFile = new File(fileName);
                // Return the parent directory of the file
                return new File(copiedFile.getParent());
             } else {
                // The query didn't work; return null
                return null;
             }
        }
    }
    ...


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值