Android学习笔记第二篇--分享数据

来源:互联网 发布:energia驱动mac 编辑:程序博客网 时间:2024/05/19 19:40

第二篇、Android分享操作

    • 第二篇Android分享操作
      • 分享简单数据
        • 向其他app发送检单数据
          • 注意
        • 接收外App传的数据
        • ActionBar 分享功能
      • 分享文件
        • 建立文件分享
        • 分享文件
        • 请求分享文件
        • 获取文件信息
      • NFC分享文件
        • 发送文件
        • 接收文件

1. 分享简单数据

  • 向其他app发送检单数据

    1. Intent发送数据必须有actions,其他对应action的activity响应事件。通过Intent实现分享功能,而ActionBar可使用ShareActionProvider来快速实现分享功能。如下是使用Intent.createChooser实现分享功能的demo:
    Intent sendIntent = new Intent();sendIntent.setAction(Intent.ACTION_SEND);sendIntent.putExtra(Intent.EXTRA_TEXT,"This is My Text to send.");sendIntent.setType("text/plain");startActivity(Intent.createChooser(sendIntent,"Share to My friends");

    如上,可以显示出多个选择框,列出可响应的分享社交App

    1. 分享二进制文件,需要指定特定的MIME类型,在EXTRA_STREAM里面放置数据的URI,如下分享一个图片的代码示例:

      Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND);shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);//重要,指定URIshareIntent.setType("image/jpeg");//指定MIME类型startActivity(Intent.createChooser(shareIntent,"Share a picture");
      注意:
      • 可以使用*/*指定MIME类型,但是仅有能够处理一般数据类型的Activity才能匹配到。因为普通的Activity不能详尽所有MIME类型。
      • 响应的Activity需要有访问URI的权限。两种方案,一是ContentProvider(per-URI permissions);二是MediaStore(亦可存储非媒体文件,Android3.0以后。)
    2. 多块内容,Multiple。同时分享不同的内容,可使用ACTION_SEND_MULTIPLE及数据URIs。而MIME需根据内容类型调整,可使用*符号。如image/jpegimage/**/*。如下:

      ArrayList<Uri> imageUris = new ArrayList<Uri>();imageUris.add(imageUri1); // Add your image URIs hereimageUris.add(imageUri2);//接收Activity需要有权限哦Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);//复合类型的MIME,ActionshareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);//传递数组shareIntent.setType("image/*");//复合MIMEstartActivity(Intent.createChooser(shareIntent, "Share images to.."));
  • 接收外App传的数据

    • Activity 在manifest文件 配置,通过Intent Filters来过滤需要处理的数据Action,如下Activity接收单张图片、文本、多张图片时,不同的intent-filer配置:

      <activity android:name=".ui.MyActivity" ><!-- 注释,单类型图片的Action过滤,其Action名称不同-->  <intent-filter>      <action android:name="android.intent.action.SEND" />      <category android:name="android.intent.category.DEFAULT" />      <data android:mimeType="image/*" />  </intent-filter><!-- 注释,文本类型的Action过滤-->  <intent-filter>      <action android:name="android.intent.action.SEND" />      <category android:name="android.intent.category.DEFAULT" />      <data android:mimeType="text/plain" />  </intent-filter><!-- 注释,多种类型图片的Action过滤-->  <intent-filter>      <action android:name="android.intent.action.SEND_MULTIPLE" />      <category android:name="android.intent.category.DEFAULT" />      <data android:mimeType="image/*" />  </intent-filter></activity>
    • 处理接收数据,通过getIntent()来获取extra数据,需要知道传递来的具体类型,结构,做相应处理。有时需要访问权限。若是数据量太大,应考虑避免UI线程的阻塞。

  • ActionBar 分享功能

    Android4.0引入ActionProvider,其子类ShareActionProvider用于分享数据。ActionBar步骤:

    1. 在Menu的xml中定义android:actionProviderClass属性。

      <menu xmlns:android="http://schemas.android.com/apk/res/android">   <item android:id="@+id/menu_item_share"       android:showAsAction="ifRoom"       android:title="Share"       android:actionProviderClass="android.widget.ShareActionProvider" /> <!--如上则声明该item需要share action provider来匹配内容 -->   ...</menu>
    2. 需要提供intent给ShareActionProvider,示例如下:

      private ShareActionProvider mShareActionProvider;...@Overridepublic boolean onCreateOptionsMenu(Menu menu) {   //菜单布局文件   getMenuInflater().inflate(R.menu.share_menu, menu);   //加载配有ShareActionProvider属性的item   MenuItem item = menu.findItem(R.id.menu_item_share);   // 实例化ShareActionProvider   mShareActionProvider = (ShareActionProvider) item.getActionProvider();   // 返回true表示显示菜单项   return true;}//回调更新intent,用于分享private void setShareIntent(Intent shareIntent) {   if (mShareActionProvider != null) {       mShareActionProvider.setShareIntent(shareIntent);   }}

2. 分享文件

​ 分享文件最为安全的方式是使用content URI,Android中FileProvider有getUriForFile()创建文件content URI。少量数据可以用intent传递。

  • 建立文件分享

    要安全地提供文件分享,需要配置Content URI。

    1. 指定FileProvider,在manifest中定义一个provider的entry,声明Authority等。如下示例:
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.myapp">    <application        ...>      <!-- authorities、meta-data的配置 -->        <provider            android:name="android.support.v4.content.FileProvider"            android:authorities="com.example.myapp.fileprovider"            android:grantUriPermissions="true"            android:exported="false">            <meta-data                android:name="android.support.FILE_PROVIDER_PATHS"                android:resource="@xml/filepaths" />          <!-- meta-data指定文件共享目录,在res/xml下 -->        </provider>        ...    </application></manifest>
    1. 共享文件的目录,res/xml中配置,filepaths.xml,如下示例:

      <paths> <!-- 每一个共享目录都是一个item,这里表示共享了files/ 目录下的子目录,files-path这个标签适用于共享应用内部储存,files/下的目录。name=“myimages” 做为content uri中的路径标记--><files-path path="images/" name="myimages"/></paths>

      <paths>有多个子标签,各自代表不同共享目录,<files-path>表示内部files/下目录,<external-path>外部存储目录,<cache-path>缓存目录。参考FileProvider。注意xml里写的目录,无法在代码中追加和修改

      • Content URI包含<provider>指定Authority(“com.example.myapp.fileprovider”);
      • 路径“myimages/”;
      • 文件名称。

      例如获取上述files/images/下的aa.jpg文件,File Provider提供的URI:

      content://com.example.myapp.fileprovider/myimages/aa.jpg

  • 分享文件

    • 上面创建了共享提供者,此处需要共享请求者。
     File requestFile = new File(mImageFilename[position]);                try {                    fileUri = FileProvider.getUriForFile(                            MainActivity.this,                            "com.example.myapp.fileprovider",                            requestFile);                } catch (IllegalArgumentException e) {                    Log.e("File Selector",                          "The selected file can't be shared: " +                          clickedFilename);                }

    需要注意的是,能获取content uri的文件,都是在manifest文件中,provider下meta-data配置了<paths>标签内的文件,否则会抛IllegalArgumentException

    • 设置文件授权:

      if(fileUri != null){//Grant temporary read permission to the content URI,授权具有临时性,一次性。mResultIntent.addFlags(Intent.FLAG_GRANT_URI_PERMISSION);}

      Caution:调用setFlags()授权文件是唯一的安全方法,应避免Context.grantUriPermission(),它需要Context.revokeUriPermission()才能撤销授权。

  • 请求分享文件

    一般文件共享分为共享者与请求者,或者服务器与客户端。服务器需要配置共享清单,客户端需要请求共享,并指定请求类型。

    • 发送文件请求,客户端startActivityForResult(),通过intent的Action,附带data,MIME去请求服务器的共享数据。服务器来显示对应的共享清单。

      java
      mRequestFileIntent = new Intent(Intent.ACTION_PICK);//Action
      mRequestFileIntent.setType("image/jpg");//MIME类型
      ...

    • 在onActivityResult()中处理服务器返回的URI,注:刚开始只是处理URI,而无任何实际的文件操作和访问,不会影响服务器文件安全

      “`java
      @Override
      public void onActivityResult(int requestCode, int resultCode,
      Intent returnIntent) {
      // If the selection didn’t work
      if (resultCode != RESULT_OK) {
      // Exit without doing anything else
      return;
      } else {
      // Get the file’s content URI from the incoming Intent
      Uri returnUri = returnIntent.getData();
      /*

      • Try to open the file for “read” access using the
      • returned URI. If the file isn’t found, write to the
      • error log and return.
        */
        try {
        /*
        * Get the content resolver instance for this context, and use it
        * to get a ParcelFileDescriptor for the file.
        */
        mInputPFD = getContentResolver().openFileDescriptor(returnUri, “r”);
        } catch (FileNotFoundException e) {
        e.printStackTrace();
        Log.e(“MainActivity”, “File not found.”);
        return;
        }
        // Get a regular file descriptor for the file,客户端利用FileDescriptor对象类操作文件。
        FileDescriptor fd = mInputPFD.getFileDescriptor();

        }
        “`
  • 获取文件信息

    上一步获取了服务器提供的content uri和file descriptor对象,但并不能操作文件,还需要指导文件信息,如大小、类型。

    • 获取文件MIME,通过ContentResolver.getType()获取uri对应的文件类型。

      java
      Uri returnUri = returnIntent.getData();
      String mimeType = getContentResolver().getType(returnUri);

    • 获取文件大小,FileProvider的query()方法返回Cuisor对象,包含对应uri的文件名称大小信息。DISPLAY_NAME,SIZE。

      “`java
      Uri returnUri = returnIntent.getData();
      Cursor returnCursor =
      getContentResolver().query(returnUri, null, null, null, null);
      /*

      • Get the column indexes of the data in the Cursor,
      • move to the first row in the Cursor, get the data,
      • and display it.
        */
        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
        returnCursor.moveToFirst();
        “`

3. NFC分享文件

Android Beam文件传输可在设备间传输大文件,API调用方便。

  • 发送文件

    使用NFC发送文件,需要设备支持NFC且app生命NFC和外部存储权限。使用URI给Android Beam来传出文件。需要满足以下要求:

    1. Android版本api>=16。

    2. 传送的文件必须在外部存储上。

    3. 文件必须全局可读,可以用File.setReadable(true,false)来设置。

    4. 必须提供文件的File URI。Android Beam无法处理FileProvider.getUriForFile生成的URI。

      <uses-permission android:name="android.permission.NFC" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORANGE" />

      其中外部存储权限在4.2.2之前不是必须声明的。

      <uses-feature android:name="android.hardware.nfc"             android:required="true" /><!-- 如此设置,声明该应用必须要硬件nfc支持才可以运行。若是required为false,则需要检测设备是否支持Android Beam-->
      • 测试Android Beam,PackageManager.hasSystemFeature()和参数FEATURE_NFC来测是nfc。Build.VERSION.SDK_INT系统版本号。
      boolean hasNFC= PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC);//判断NFC可用与否。Build.VERSION.SDK_INT<Build.VERSION_CODE.JELLY_BEAN_MR1//版本低。//可用的话,实例化NfcAdapterNfcAdapter adapter = NfcAdatper.getDefaultAdapter(this);
      • 通过回调函数获取数据
      private Uri[] mFileUris = new Uri[10];//提供给AndroidBeam的URIsprivate class FileUriCallback implements NfcAdapter.CreateBeamUrisCallback{public FileUriCallback(){}@overridepublic Uri[] createBeamUris(NfcEvent event){  return mFileUris;}}

      通过setBeamPushUrisCallback()将回调提供给Android Beam文件传输。

      mFileUriCallback = new FileUriCallback();mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this);
      • 指定要发送的文件,给文件File URI,然后加入URIs数组。记住需要有文件的读取权限。
  • 接收文件

    Android Beam文件传输时,是将文件copy到某特殊目录,然后由Media Scanner扫描文件,在MediaStore Provider中为媒体文件添加条目记录。

    • 响应传输来的请求,并显示数据。

      Android Beam传输数据到接收设备后,会发送Intent通知,包含ACTION_VIEW,MIME,URI。用户确认通知后,intent被发至系统,寻求其他响应。

      Activity在manifest配置<intent-filter>加入<action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.CATEGORY_DEFAULT"<data android:nimeType="mime-type"分别标识不同的Action,category和数据type。

      Action_view的action也不一定就是Android beam发送的。*

      <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>
    • 读取文件需要权限

      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

      上面所说,ACTION_VIEW不一定就是AndroidBeam发送的intent,所以需要检查Scheme和Authority。调用Uri.getScheme。

      mIntent = getIntent();//判断Action,机器Scheme和AuthorityUri beamUri = mIntent.getData();beamUri.getScheme();//判断是否是“file”,或者“content”
    • File URI中获取目录

      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();  }
    • Content URI中获取目录,MediaS tore会含有文件的uri信息。Uri.getAuthority()获取authority,返回值MediaStore.AUTHORITY或者其他。

      为其他类型时候,不一定可以获取目录;

文章为阅读Android官方培训教程而摘记,仅供小白个人学习笔记

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕妇感冒流鼻涕打喷嚏怎么办 孕妇感冒咳嗽流鼻涕怎么办 鼻子痒流鼻涕流眼泪怎么办 天冷鼻子流鼻涕怎么办 感冒流水样鼻涕怎么办 一直有清水鼻涕怎么办 孩子总打喷嚏鼻塞怎么办 4岁儿童流鼻涕怎么办 孕妇清鼻涕不停怎么办 感冒流鼻水怎么办速效办法 一岁宝宝流清涕怎么办 咳嗽喉咙痛有痰怎么办 冻感冒了流鼻涕怎么办 吸烟经常嗓子疼怎么办 擦鼻涕擦破了怎么办 感冒鼻水流不停怎么办 流鼻涕鼻子都擦红了怎么办 鼻子不停的流水怎么办 擦鼻涕耳朵疼怎么办 鼻涕跟水一样怎么办 鼻涕水多打喷嚏怎么办 买来的鼻涕泥是水怎么办? 鼻炎鼻涕跟水怎么办 出门忘记带钥匙怎么办 总留鼻涕水怎么办 流像水一样的鼻涕怎么办 出门忘记带洗面奶怎么办 一侧鼻子流清水怎么办 慢性肠胃炎犯了怎么办 儿子拉肚肚子疼怎么办 皮肤太容易过敏怎么办 过敏脸一直不好怎么办 脸上突然过敏怎么办急救 脸过敏发红疼怎么办 脸上突然过敏了怎么办 脸过敏总反复怎么办 用蜂蜜洗脸过敏怎么办 脸上涂蜂蜜过敏怎么办 孕晚期脸过敏怎么办 吃芒果脸过敏怎么办 脸上老反复过敏怎么办