Android 如何截取屏幕截图并以编程方式共享

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10296711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:11:32  来源:igfitidea点击:

How to take a screenshot and share it programmatically

androidscreenshot

提问by ρяσ?ρ?я K

I am making an application in Android in which I have to take screenshot of one of my activities and mail it as attachment.

我正在 Android 中制作一个应用程序,我必须在其中截取我的一项活动的屏幕截图并将其作为附件邮寄。

I want to take screenshot of the current page and then share it via email, Bluetooth, Twitter or Facebook.

我想截取当前页面的屏幕截图,然后通过电子邮件、蓝牙、Twitter 或 Facebook 进行分享。

My code is as follows:

我的代码如下:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  MenuInflater inflater = getMenuInflater();
  inflater.inflate(R.menu.menuselected1, menu);
  return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

  switch (item.getItemId()) {
    case R.id.ScreenShot:

    try {
        takeScreenShot(this);
    }
    catch (Exception e) {
        System.out.println(e);
    }

    return true;

    default:
    return super.onOptionsItemSelected(item);
  }
}

private static void savePic(Bitmap b, String strFileName) {
  FileOutputStream fos = null;
  try {
      fos = new FileOutputStream(strFileName);
      if (null != fos) {
        b.compress(Bitmap.CompressFormat.PNG, 90, fos);
        System.out.println("b is:"+b);
        fos.flush();
        fos.close();
      }
  } catch (FileNotFoundException e) {
          e.printStackTrace();
  } catch (IOException e) {
          e.printStackTrace();
  }
}

public static void shoot(Activity a,String b) {
  //savePic(takeScreenShot(a), "sdcard/xx.png");
  savePic(takeScreenShot(a), b);
}

private static Bitmap takeScreenShot(Activity activity) {
  View view = activity.getWindow().getDecorView();
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap b1 = view.getDrawingCache();
  Rect frame = new Rect();
  activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  int statusBarHeight = frame.top;
  int width = activity.getWindowManager().getDefaultDisplay().getWidth();
  int height = activity.getWindowManager().getDefaultDisplay()
               .getHeight();

  // Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);
  Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height
                                 - statusBarHeight);
  view.destroyDrawingCache();
  return b;
}

回答by ρяσ?ρ?я K

Try this for taking screenshot of current Activity:

试试这个来截取当前活动的截图:

Android 2.2 :

安卓 2.2:

private static Bitmap takeScreenShot(Activity activity)
{
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap b1 = view.getDrawingCache();
    Rect frame = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    int statusBarHeight = frame.top;

    DisplayMetrics displaymetrics = new DisplayMetrics(); 
    mContext.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);

    int width = displaymetrics.widthPixels;
    int height = displaymetrics.heightPixels;

    Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height  - statusBarHeight);
    view.destroyDrawingCache();
    return b;
}
private static void savePic(Bitmap b, String strFileName)
{
    FileOutputStream fos = null;
    try
    {
        fos = new FileOutputStream(strFileName);
        if (null != fos)
        {
            b.compress(Bitmap.CompressFormat.PNG, 90, fos);
            fos.flush();
            fos.close();
        }
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

回答by CommonsWare

If by "screenshot of current page" you mean "screenshot of one of my activities", you can arrange to render your Viewsto a bitmap-backed Canvas, then save an image from the bitmap.

如果“当前页面的屏幕截图”是指“我的一个活动的屏幕截图”,您可以安排将您的渲染Views为位图支持Canvas,然后从位图保存图像

If by "screenshot of current page" you mean "screenshot of somebody else's activity", that is not supported by the Android SDK, for obvious privacy and security reasons. There are various techniques that rooted device users can use to take screenshots.

如果“当前页面的屏幕截图”是指“其他人活动的屏幕截图”,Android SDK 不支持,出于明显的隐私和安全原因。有根设备用户可以使用各种技术来截取屏幕截图。

回答by Chase Roberts

1. Create the share button

1. 创建分享按钮

I wanted mine in the action bar so I created a share_menu.xml file:

我想在操作栏中使用我的,所以我创建了一个 share_menu.xml 文件:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/share_item"
        app:showAsAction="always|withText"
        android:title="Share"
        android:icon="@drawable/share_icon"
        android:actionProviderClass=
            "android.widget.ShareActionProvider" />
</menu>

This adds a button in the action bar with my share_icon and the text.

这会在操作栏中添加一个带有我的 share_icon 和文本的按钮。

2. Add the sharing menu to your activity (or fragment)

2. 将分享菜单添加到您的活动(或片段)

I did this inside a fragment so I added the code below to my fragment file. If you are inside an activity then you override public boolean onCreateOptionsMenu(Menu menu)instead.

我在一个片段中做了这个,所以我将下面的代码添加到我的片段文件中。如果您在活动中,那么您可以改写public boolean onCreateOptionsMenu(Menu menu)

@Override
public void onCreateOptionsMenu(
        Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.share_menu, menu);
}

if you are doing this with a fragment then in onCreate()you have to add:

如果您使用片段执行此操作,则onCreate()必须添加:

setHasOptionsMenu(true);

3. Set up button action/callback/onclick

3.设置按钮动作/回调/onclick

This is what is going to kick off the sharing.

这就是分享的开始。

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.share_item){
            Bitmap bm = screenShot(this.getView());
            File file = saveBitmap(bm, "mantis_image.png");
            Log.i("chase", "filepath: "+file.getAbsolutePath());
            Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));
            Intent shareIntent = new Intent();
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.putExtra(Intent.EXTRA_TEXT, "Check out my app.");
            shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
            shareIntent.setType("image/*");
            shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivity(Intent.createChooser(shareIntent, "share via"));
        }
        return super.onOptionsItemSelected(item);
    }

Notice this calls two magic methods:

注意这调用了两个魔术方法:

screenShot():

截屏():

private Bitmap screenShot(View view) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),view.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}

private static File saveBitmap(Bitmap bm, String fileName){
    final String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Screenshots";
    File dir = new File(path);
    if(!dir.exists())
        dir.mkdirs();
    File file = new File(dir, fileName);
    try {
        FileOutputStream fOut = new FileOutputStream(file);
        bm.compress(Bitmap.CompressFormat.PNG, 90, fOut);
        fOut.flush();
        fOut.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return file;
}

Important

重要的

To your AndroidManifest.xml, you have to add:

到您的AndroidManifest.xml,您必须添加:

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

or the screenshot won't be saved, and gmail will think you are trying to attach an empty file.

否则屏幕截图将不会被保存,并且 gmail 会认为您正在尝试附加一个空文件。

Also, a lot of SO answers say to use "*/*"for shareIntent.setType()but this creates an issue with facebook sharing, so it's best to leave it as "image/*".

此外,很多 SO 答案都说要使用"*/*"forshareIntent.setType()但这会导致 facebook 共享出现问题,因此最好将其保留为"image/*".

回答by Hamed Jaliliani

Kotlin complete solution Code with permission check :

带有权限检查的 Kotlin 完整解决方案代码:

1- Use this nice library to take screen shot with java / Kotlin / Rx functionality, add library dependency : InstaCapture github link

1- 使用这个不错的库来使用 java / Kotlin / Rx 功能截取屏幕截图,添加库依赖项: InstaCapture github 链接

 implementation "com.github.tarek360:instacapture:2.0.1"

2- Must check permission for compatibility on all android versions:

2- 必须检查所有 android 版本的兼容性许可:

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) != PackageManager.PERMISSION_GRANTED
        ) { // Needs permission so request it
            DeviceUtil.showAlertMsg(this, GeneralDicModel.shareMsgScreenShot!!)
            requestPermissions(
                arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
            )   //callback  result to onRequestPermissionsResult
        } else { //Has got the permission before or doesn't need
            screenShotAndShareIt()
        }

3- Check permission result :

3-检查权限结果:

 override fun onRequestPermissionsResult(
    requestCode: Int, permissions: Array<out String>,
    grantResults: IntArray
) {
    when (requestCode) {
        PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                screenShotAndShareIt()
            } else {
                //  toast("Permission must be granted in order to save scrrenshot file")
            }
        }
    }
}

4- Func call for take Screenshot & Share it by intent :

4- Func 调用截屏并按意图分享:

 fun screenShotAndShareIt() {
    Instacapture.capture(this, object : SimpleScreenCapturingListener() {
    override fun onCaptureComplete(bitmap: Bitmap) {
    val state = Environment.getExternalStorageState()
            if (Environment.MEDIA_MOUNTED == state) {
                val path: String = Environment.getExternalStorageDirectory().toString()  
                val picDir = File(path.plus("/myPic"))
                if (!picDir.exists()) {
                    picDir.mkdir()
                }
                var bitmapScreenShot = bitmap
                val fileName = "screenshot" + ".jpg"
                val picFile = File(picDir.path.plus("/" + fileName))
                try {
                    picFile.createNewFile()
                    val picOut = FileOutputStream(picFile)
                    bitmapScreenShot =
                        Bitmap.createBitmap(bitmapScreenShot, 0, 0, bitmapScreenShot.width, bitmapScreenShot.height)
                    val saved: Boolean = bitmapScreenShot.compress(Bitmap.CompressFormat.JPEG, 100, picOut)
                    if (saved) {
                        Log.i(
                            TAG,
                            "ScreenShotAndShareIt : Image saved to your device Pictures " + "directory! + ${picFile.absolutePath}"
                        )
                    } else {
                        Log.i(TAG, "ScreenShotAndShareIt Error on Save! + ${picFile.absolutePath}")
                    }
                    picOut.close()

                    // share via intent
                    val intent: Intent = Intent(android.content.Intent.ACTION_SEND)
                    intent.type = "image/jpeg"
                    intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(picFile.absolutePath))
                    startActivity(Intent.createChooser(intent, "Sharing"))
                } catch (e: Exception) {
                    Log.i(TAG, "ScreenShotAndShareIt Error catch : " + e.printStackTrace())
                }
            } else {
                //Error
                Log.i(TAG, "ScreenShotAndShareIt Error Environment.MEDIA_MOUNTED == state : " )
            }
 }
 })

5- Declare this variable :

5- 声明这个变量:

val PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 100

6- Do not forget to Add this permissions to AndroidManifest.xml:

6- 不要忘记将此权限添加到 AndroidManifest.xml:

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

回答by Van Toan Vu

This is how I captured the screen and shared it. Take a look if you are interested.

这就是我捕获屏幕并共享的方式。有兴趣的话就看看吧。

public Bitmap takeScreenshot() {
  View rootView = findViewById(android.R.id.content).getRootView();
  rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
 }

And the method that saves the bitmap image to external storage:

以及将位图图像保存到外部存储的方法:

public void saveBitmap(Bitmap bitmap) {
  File imagePath = new File(Environment.getExternalStorageDirectory() +       "/screenshot.png");
  FileOutputStream fos;
  try {
  fos = new FileOutputStream(imagePath);
  bitmap.compress(CompressFormat.JPEG, 100, fos);
 fos.flush();
 fos.close();
 } catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}}

see more in : https://www.youtube.com/watch?v=LRCRNvzamwY&feature=youtu.be

查看更多:https: //www.youtube.com/watch?v=LRCRNvzamwY&feature=youtu.be