android之如何在不使用外部存储的情况下拍摄和分享屏幕截图

qq78292959 阅读:135 2025-02-15 21:57:57 评论:0

我想以编程方式截取屏幕截图并使用 ShareActionProvider 共享它,而无需请求“android.permission.WRITE_EXTERNAL_STORAGE”权限。 我正在尝试这样做,因为我想避免在不是绝对必要的情况下请求权限,并且能够在没有外部存储的情况下处理设备。

我设法成功地将屏幕截图发送到一些应用程序,但至少有一个 (Gmail) 不会附加我的屏幕截图。 这是我的代码:

... 
@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
    ... 
    MenuItem shareMenuItem = menu.findItem(R.id.action_share); 
    ShareActionProvider shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareMenuItem); 
    shareActionProvider.setShareIntent(createShareIntent()); 
    shareActionProvider.setOnShareTargetSelectedListener(new ShareActionProvider.OnShareTargetSelectedListener() 
    { 
        @Override 
        public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) 
        { 
            saveScreenshot(); 
            // The return result is ignored. Return false for consistency. 
            return false; 
        } 
    }); 
} 
 
private Intent createShareIntent() { 
    // Get the path of the screenshot inside the directory holding application files. 
    File screenshotFile = new File(getActivity().getApplicationContext().getFilesDir(), SCREENSHOT_NAME); 
 
    Intent shareIntent = new Intent(Intent.ACTION_SEND); 
    shareIntent.setType("image/jpeg"); 
    shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(screenshotFile)); 
    return shareIntent; 
} 
 
private void saveScreenshot() { 
    view.setDrawingCacheEnabled(true); 
    Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache()); 
    view.setDrawingCacheEnabled(false); 
 
    // Save on Internal Storage to avoid asking for WRITE_EXTERNAL_STORAGE permission. 
    FileOutputStream outputStream = null; 
    try { 
        // Open a file associated with this Context's application package for writing. 
        // Make file readable by other apps otherwise it can't be shared. 
        outputStream = getActivity().getApplicationContext() 
                .openFileOutput(SCREENSHOT_NAME, Context.MODE_WORLD_READABLE); 
        bitmap.compress(Bitmap.CompressFormat.JPEG, COMPRESS_QUALITY, outputStream); 
        outputStream.close(); 
    } catch (IOException e) { 
        Log.e(LOG_TAG, "Can't save screenshot!", e); 
    } finally { 
        if (outputStream != null) { 
            try { 
                outputStream.close(); 
            } catch (IOException e) { 
                Log.e(LOG_TAG, "Can't close the output stream!", e); 
            } 
        } 
    } 
} 
... 

如果我想与 Twitter、Hangouts、Keep、Evernote、Google 的 Inbox 和我测试过的其他应用程序共享,此代码有效,但不适用于 Gmail。 例如,在 Nexus 6 上,Gmail 给我一条 Toast 消息,内容为“Permission denied”,而在 Nexus 4 上,它只是不附上没有任何错误消息的屏幕截图。 日志中没有任何相关内容。 使用类似的东西

screenshotFile.setReadable(true, false); 

try { 
    Runtime.getRuntime().exec("chmod 777 " + screenshotFile.getAbsolutePath()); 
} catch (IOException e) { 
    Log.e(LOG_TAG, "Can't give permissions to screenshot file!", e); 
} 

没有区别。

如果我使用 Environment.getExternalStorageDirectory() 将我的屏幕截图保存在外部存储上并请求“android.permission.WRITE_EXTERNAL_STORAGE”权限,我测试的所有应用程序都可以正常工作.

如何在不使用外部存储的情况下执行此操作并让所有应用程序(包括 Gmail)正常运行? 这可能是 Gmail 应用程序的问题吗? 或者你会建议我只请求在外部存储上写入的权限并接受我的一些用户可能会提示并且一些设备没有 SD 卡的事实吗?

谢谢!

请您参考如下方法:

这是您使用 fileprovider 实现所需内容所必须执行的操作。我已经在我的应用程序中完成了。

创建一个文件作为 res/xml/paths.xml 并添加这个

<?xml version="1.0" encoding="utf-8"?> 
<paths > 
    <cache-path name="shared_images" path="images/"/> 
</paths> 

然后在你的 AndroidManifest.xml 中声明 fileprovider android 用你的包名替换 android:authorities 属性

<provider 
        android:name="android.support.v4.content.FileProvider" 
        android:authorities="com.harkunwar.testapp.fileprovider" 
        <!--put your package name here--> 
        android:exported="false" 
        android:grantUriPermissions="true"> 
        <meta-data 
            android:name="android.support.FILE_PROVIDER_PATHS" 
            android:resource="@xml/paths" /> 
            <!--put your xml file name here--> 
</provider> 

然后用这个方法分享你的Bitmap

void share(Bitmap bitmap) { 
    String fileName = "share.png"; 
    File dir = new File(getCacheDir(), "images"); 
    dir.mkdirs(); 
    File file = new File(dir, fileName); 
    try { 
        FileOutputStream fOut = new FileOutputStream(file); 
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut); 
        fOut.flush(); 
        fOut.close(); 
     } catch (Exception e) { 
        e.printStackTrace(); 
     } 
     Uri uri = FileProvider.getUriForFile(this, getPackageName()+".fileprovider", file); 
 
     Intent intent = new Intent(); 
     intent.setAction(Intent.ACTION_SEND); 
     intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
     intent.setType("image/*"); 
     intent.setDataAndType(uri, getContentResolver().getType(uri)); 
     intent.putExtra(Intent.EXTRA_SUBJECT, ""); 
     intent.putExtra(Intent.EXTRA_TEXT, "Here's the shared image"); 
     intent.putExtra(Intent.EXTRA_STREAM, uri); 
 
      try { 
         startActivity(Intent.createChooser(intent, "Share Image")); 
      } catch (ActivityNotFoundException e) { 
         Toast.makeText(this, "No App Available", Toast.LENGTH_SHORT).show(); 
      } 
} 

然后我使用这个简单的代码来分享使用之前功能的屏幕截图。

View rootView = getWindow().getDecorView().findViewById(android.R.id.content); 
Bitmap screenshot = getScreenShot(rootView); 
share(screenshot); 


标签:Android
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号