Android 官网Train阅读记录——3

来源:互联网 发布:unity3d c 工具类脚本 编辑:程序博客网 时间:2024/06/14 20:48

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 hereimageUris.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
原创粉丝点击