如何截屏当前Activity然后分享?

How to take a screenshot of a current Activity and then share it?

我需要截取 Activity 的屏幕截图(没有标题栏,用户不应该看到实际截取的屏幕截图),然后通过操作菜单按钮分享它 "share".我已经尝试了一些解决方案,但它们对我不起作用。有什么想法吗?

您可以使用以下代码获取您在屏幕上看到的视图的位图。您可以指定要创建位图的视图。

    public static Bitmap getScreenShot(View view) {
           View screenView = view.getRootView();
           screenView.setDrawingCacheEnabled(true);
           Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
           screenView.setDrawingCacheEnabled(false);
           return bitmap;
     }

您可以对您的任何部分进行截图 view.You 只需要参考您想要截图的布局。例如,在您的情况下,您想要 activity 的屏幕截图。假设您的 activity 根布局是 Linear Layout 。

   // find the reference of the layout which screenshot is required

     LinearLayout LL = (LinearLayout) findViewById(R.id.yourlayout);
      Bitmap screenshot = getscreenshot(LL);

     //use this method to get the bitmap
      private Bitmap getscreenshot(View view) {
        View v = view;
        v.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());
        return bitmap;
      }

这就是我截屏并分享的方式。

首先,从当前activity获取根视图:

View rootView = getWindow().getDecorView().findViewById(android.R.id.content);

第二个,捕获根视图:

 public static Bitmap getScreenShot(View view) {
       View screenView = view.getRootView();
       screenView.setDrawingCacheEnabled(true);
       Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
       screenView.setDrawingCacheEnabled(false);
       return bitmap;
 }

第三,将Bitmap存入SDCard:

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

最后,分享当前Activity的截图:

private void shareImage(File file){
    Uri uri = Uri.fromFile(file);
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_SEND);
    intent.setType("image/*");

    intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
    intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
    intent.putExtra(Intent.EXTRA_STREAM, uri);
    try {
        startActivity(Intent.createChooser(intent, "Share Screenshot"));
    } catch (ActivityNotFoundException e) {
        Toast.makeText(context, "No App Available", Toast.LENGTH_SHORT).show();
    }
}

希望你能从我的代码中得到启发。

更新:

将以下权限添加到您的 AndroidManifest.xml:

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

因为它在外部存储中创建和访问文件。

更新:

从Android 7.0 Nougat 开始,禁止共享文件链接。要解决这个问题,您必须实施 FileProvider 并共享 "content://" uri 而不是 "file://" uri.

很好地描述了如何去做。

在添加

之前,我无法让 开始工作
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

给我的 AndroidManifest.xml.

这就是我截屏并分享的方式。感兴趣的可以看看

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

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

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);
 }}

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

通过点击侦听器创建分享按钮

    share = (Button)findViewById(R.id.share);
    share.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Bitmap bitmap = takeScreenshot();
            saveBitmap(bitmap);
            shareIt();
        }
    });

添加两个方法

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

public void saveBitmap(Bitmap bitmap) {
    imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
    FileOutputStream fos;
    try {
        fos = new FileOutputStream(imagePath);
        bitmap.compress(Bitmap.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);
    }
}

分享屏幕截图。在这里分享实现

    private void shareIt() {
    Uri uri = Uri.fromFile(imagePath);
    Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
    sharingIntent.setType("image/*");
    String shareBody = "In Tweecher, My highest score with screen shot";
    sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Tweecher score");
    sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
    sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);

    startActivity(Intent.createChooser(sharingIntent, "Share via"));
    }

对于所有 Xamarin 用户:

Xamarin.Android代码:

创建一个外部 Class(我有每个平台的接口,我从 android 平台实现了以下 3 个功能):

    public static Bitmap TakeScreenShot(View view)
    {
        View screenView = view.RootView;
        screenView.DrawingCacheEnabled = true;
        Bitmap bitmap = Bitmap.CreateBitmap(screenView.DrawingCache);
        screenView.DrawingCacheEnabled = false;
        return bitmap;
    }
    public static Java.IO.File StoreScreenShot(Bitmap picture)
    {
        var folder = Android.OS.Environment.ExternalStorageDirectory + Java.IO.File.Separator + "MyFolderName";
        var extFileName = Android.OS.Environment.ExternalStorageDirectory +
                          Java.IO.File.Separator +
                          Guid.NewGuid() + ".jpeg";
        try
        {
            if (!Directory.Exists(folder))
                Directory.CreateDirectory(folder);

            Java.IO.File file = new Java.IO.File(extFileName);

            using (var fs = new FileStream(extFileName, FileMode.OpenOrCreate))
            {
                try
                {
                    picture.Compress(Bitmap.CompressFormat.Jpeg, 100, fs);
                }
                finally
                {
                    fs.Flush();
                    fs.Close();
                }
                return file;
            }
        }
        catch (UnauthorizedAccessException ex)
        {
            Log.Error(LogPriority.Error.ToString(), "-------------------" + ex.Message.ToString());
            return null;
        }
        catch (Exception ex)
        {
            Log.Error(LogPriority.Error.ToString(), "-------------------" + ex.Message.ToString());
            return null;
        }
    }
    public static void ShareImage(Java.IO.File file, Activity activity, string appToSend, string subject, string message)
    {
        //Push to Whatsapp to send
        Android.Net.Uri uri = Android.Net.Uri.FromFile(file);
        Intent i = new Intent(Intent.ActionSendMultiple);
        i.SetPackage(appToSend); // so that only Whatsapp reacts and not the chooser
        i.AddFlags(ActivityFlags.GrantReadUriPermission);
        i.PutExtra(Intent.ExtraSubject, subject);
        i.PutExtra(Intent.ExtraText, message);
        i.PutExtra(Intent.ExtraStream, uri);
        i.SetType("image/*");
        try
        {
            activity.StartActivity(Intent.CreateChooser(i, "Share Screenshot"));
        }
        catch (ActivityNotFoundException ex)
        {
            Toast.MakeText(activity.ApplicationContext, "No App Available", ToastLength.Long).Show();
        }
    }`

现在,根据您的 Activity,您 运行 上面的代码如下:

                    RunOnUiThread(() =>
                {
                    //take silent screenshot
                    View rootView = Window.DecorView.FindViewById(Resource.Id.ActivityLayout);
                    Bitmap tmpPic = ShareHandler.TakeScreenShot(this.CurrentFocus); //TakeScreenShot(this);
                    Java.IO.File imageSaved = ShareHandler.StoreScreenShot(tmpPic);
                    if (imageSaved != null)
                    {
                        ShareHandler.ShareImage(imageSaved, this, "com.whatsapp", "", "ScreenShot Taken from: " + "Somewhere");
                    }
                });

希望对大家有用。

用于截图

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

用于保存屏幕截图

private void saveBitmap(Bitmap bitmap) {
    imagePath = new File(Environment.getExternalStorageDirectory() + "/scrnshot.png"); ////File imagePath
    FileOutputStream fos;
    try {
        fos = new FileOutputStream(imagePath);
        bitmap.compress(Bitmap.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);
    }
}

并用于分享

private void shareIt() {
    Uri uri = Uri.fromFile(imagePath);
    Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
    sharingIntent.setType("image/*");
    String shareBody = "My highest score with screen shot";
    sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Catch score");
    sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
    sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);

    startActivity(Intent.createChooser(sharingIntent, "Share via"));
}

并且只需在 onclick 中您就可以调用这些方法

shareScoreCatch.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Bitmap bitmap = takeScreenshot();
        saveBitmap(bitmap);
        shareIt();
   }
});

这是我用来截图的。上述解决方案适用于 API < 24,但对于 API 24 和更大,则需要另一个解决方案。我已经在 API 15、24 和 27 上测试了这个方法。

我在MainActivity.java中放置了以下方法:

public class MainActivity {

...

String[] permissions = new String[]{"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"};
View sshotView;

...

private boolean checkPermission() {
List arrayList = new ArrayList();
for (String str : this.permissions) {
if (ContextCompat.checkSelfPermission(this, str) != 0) {
arrayList.add(str);
}
}
if (arrayList.isEmpty()) {
return true;
}
ActivityCompat.requestPermissions(this, (String[]) arrayList.toArray(new String[arrayList.size()]), 100);
return false;
}

protected void onCreate(Bundle savedInstanceState) {
...

this.sshotView = getWindow().getDecorView().findViewById(R.id.parent);
...

}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

int id = item.getItemId();
switch (id) {


case R.id.action_shareScreenshot:
boolean checkPermission = checkPermission();
Bitmap screenShot = getScreenShot(this.sshotView);
if (!checkPermission) {
return true;
}
shareScreenshot(store(screenShot));
return true;

case R.id.option2:      
...    
return true;
}

return false;
}

private void shareScreenshot(File file) {
Parcelable fromFile = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".com.redtiger.applehands.provider", file);
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setAction("android.intent.action.SEND");
intent.setType("image/*");
intent.putExtra("android.intent.extra.SUBJECT", XmlPullParser.NO_NAMESPACE);
intent.putExtra("android.intent.extra.TEXT", XmlPullParser.NO_NAMESPACE);
intent.putExtra("android.intent.extra.STREAM", fromFile);
try {
startActivity(Intent.createChooser(intent, "Share Screenshot"));
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), "No Communication Platform Available", Toast.LENGTH_SHORT).show();
}
}

public static Bitmap getScreenShot(View view) {
View rootView = view.getRootView();
rootView.setDrawingCacheEnabled(true);
Bitmap createBitmap = Bitmap.createBitmap(rootView.getDrawingCache());
rootView.setDrawingCacheEnabled(false);
return createBitmap;

public File store(Bitmap bitmap) {
String str = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/Screenshots";
File file = new File(str);
if (!file.exists()) {
file.mkdirs();
}
file = new File(str + "/sshot.png");
try {
OutputStream fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 80, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "External Storage Permission Is Required", Toast.LENGTH_LONG).show();
}
return file;
}
}

我在 AndroidManifest.xml 中设置了以下权限和提供程序:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.redtiger.applehands">

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

<application

...

<provider
android:name="com.redtiger.applehands.util.GenericFileProvider"
android:authorities="${applicationId}.com.redtiger.applehands.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>

...

</application>

</manifest>

我创建了一个名为 provider_paths.xml 的文件(请参阅下文)来指示 FileProvider 将屏幕截图保存在何处。该文件包含一个指向外部目录根目录的简单标记。

文件放置在资源文件夹 res/xml 中(如果此处没有 xml 文件夹,只需创建一个并将文件放在那里)。

provider_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>

如果有人得到 java.io.FileNotFoundException,按照 SilengKnight 的解决方案,问题可能是不允许写入存储(尽管我们在清单中添加了用户权限)。我通过在创建新的 FileOutputStream 之前在存储函数中添加它来解决它。

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        //Permission was denied
        //Request for permission
        ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                MY_PERMISSIONS_CODE_EXTERNAL_STORAGE);
    }

您可以尝试使用以下代码捕获当前屏幕的屏幕截图并在没有任何 LIBRARY & PERMISSION 的情况下共享该图像。我已经测试过它的完美运行。

只需复制粘贴即可。

  1. 在MainAtivity.java

     public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        private Button fullPageScreenshot, customPageScreenshot;
        private LinearLayout rootContent;
        private ImageView imageView;
        private TextView hiddenText;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy(builder.build());
            findViews();
            implementClickEvents();
        }
        /*  Find all views Ids  */
        private void findViews() {
            fullPageScreenshot = (Button) findViewById(R.id.full_page_screenshot);
            customPageScreenshot = (Button) findViewById(R.id.custom_page_screenshot);
            rootContent = (LinearLayout) findViewById(R.id.root_content);
            imageView = (ImageView) findViewById(R.id.image_view);
            hiddenText = (TextView) findViewById(R.id.hidden_text);
        }
        /*  Implement Click events over Buttons */
        private void implementClickEvents() {
            fullPageScreenshot.setOnClickListener(this);
            customPageScreenshot.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.full_page_screenshot:
                    takeScreenshot(ScreenshotType.FULL);
                    break;
                case R.id.custom_page_screenshot:
                    takeScreenshot(ScreenshotType.CUSTOM);
                    break;
            }
        }
    
        /*  Method which will take screenshot on Basis of Screenshot Type ENUM  */
        private void takeScreenshot(ScreenshotType screenshotType) {
            Bitmap b = null;
            switch (screenshotType) {
                case FULL:
                    //If Screenshot type is FULL take full page screenshot i.e our root content.
                    b = ScreenshotUtils.getScreenShot(rootContent);
                    break;
                case CUSTOM:
                    //If Screenshot type is CUSTOM
                    fullPageScreenshot.setVisibility(View.INVISIBLE);//set the visibility to INVISIBLE of first button
                    hiddenText.setVisibility(View.VISIBLE);//set the visibility to VISIBLE of hidden text
                     b = ScreenshotUtils.getScreenShot(rootContent);
                    //After taking screenshot reset the button and view again
                    fullPageScreenshot.setVisibility(View.VISIBLE);//set the visibility to VISIBLE of first button again
                    hiddenText.setVisibility(View.INVISIBLE);//set the visibility to INVISIBLE of hidden text
                    //NOTE:  You need to use visibility INVISIBLE instead of GONE to remove the view from frame else it wont consider the view in frame and you will not get screenshot as you required.
                    break;
            }
            //If bitmap is not null
            if (b != null) {
                showScreenShotImage(b);//show bitmap over imageview
                File saveFile = ScreenshotUtils.getMainDirectoryName(this);//get the path to save screenshot
                File file = ScreenshotUtils.store(b, "screenshot" + screenshotType + ".jpg", saveFile);//save the screenshot to selected path
                shareScreenshot(file);//finally share screenshot
            } else
                //If bitmap is null show toast message
                Toast.makeText(this, R.string.screenshot_take_failed, Toast.LENGTH_SHORT).show();
        }
        /*  Show screenshot Bitmap */
        private void showScreenShotImage(Bitmap b) {
            imageView.setImageBitmap(b);
        }
        /*  Share Screenshot  */
        private void shareScreenshot(File file) {
            Uri uri = Uri.fromFile(file);//Convert file path into Uri for sharing
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("image/*");
            intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
            intent.putExtra(android.content.Intent.EXTRA_TEXT, getString(R.string.sharing_text));
            intent.putExtra(Intent.EXTRA_STREAM, uri);//pass uri here
            startActivity(Intent.createChooser(intent, getString(R.string.share_title)));
        }
    }
    
    1. ScreenshotType.java

      public enum ScreenshotType {
          FULL, CUSTOM;
      }
      
    2. ScreenshotUtils.java

      public class ScreenshotUtils {

      /*  Method which will return Bitmap after taking screenshot. We have to pass the view which we want to take screenshot.  */
      public static Bitmap getScreenShot(View view) {
          View screenView = view.getRootView();
          screenView.setDrawingCacheEnabled(true);
          Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
          screenView.setDrawingCacheEnabled(false);
          return bitmap;
      }
      
      
      /*  Create Directory where screenshot will save for sharing screenshot  */
      public static File getMainDirectoryName(Context context) {
          //Here we will use getExternalFilesDir and inside that we will make our Demo folder
          //benefit of getExternalFilesDir is that whenever the app uninstalls the images will get deleted automatically.
          File mainDir = new File(
                  context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Demo");
      
          //If File is not present create directory
          if (!mainDir.exists()) {
              if (mainDir.mkdir())
                  Log.e("Create Directory", "Main Directory Created : " + mainDir);
          }
          return mainDir;
      }
      
      /*  Store taken screenshot into above created path  */
      public static File store(Bitmap bm, String fileName, File saveFilePath) {
          File dir = new File(saveFilePath.getAbsolutePath());
          if (!dir.exists())
              dir.mkdirs();
          File file = new File(saveFilePath.getAbsolutePath(), fileName);
          try {
              FileOutputStream fOut = new FileOutputStream(file);
              bm.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
              fOut.flush();
              fOut.close();
          } catch (Exception e) {
              e.printStackTrace();
          }
          return file;
      
      
      
      }
      

      }

4.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context="com.takescreenshot_demo.MainActivity">

    <!--  Button which will take full page screenshot  -->
    <Button
        android:id="@+id/full_page_screenshot"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/full_page_screenshot"
        android:textColor="@android:color/white"
        android:textSize="14sp" />

    <!--   Hidden Text which will shown when taking screenshot from below Button  -->
    <TextView
        android:id="@+id/hidden_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/hidden_text"
        android:textColor="@android:color/white"
        android:textSize="14sp"
        android:visibility="invisible" />

    <!--  Button which will take screenshot after hiding some view and showing some view  -->
    <Button
        android:id="@+id/custom_page_screenshot"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/custom_page_screenshot"
        android:textColor="@android:color/white"
        android:textSize="14sp" />


    <!--  ImageView to show taken Screenshot  -->
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        android:src="@mipmap/ic_launcher" />

</LinearLayout>

合并复制粘贴代码:

private void takeScreenshot() {
        Date now = new Date();
        android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

        try {
            // image naming and path  to include sd card  appending name you choose for file
            String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
            String screenshotPath = mPath;

            // create bitmap screen capture
            View v1 = getWindow().getDecorView().getRootView();
            v1.setDrawingCacheEnabled(true);
            Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
            v1.setDrawingCacheEnabled(false);

            File imageFile = new File(mPath);

            FileOutputStream outputStream = new FileOutputStream(imageFile);
            int quality = 100;
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
            outputStream.flush();
            outputStream.close();

//            openScreenshot(imageFile);
        } catch (Throwable e) {
            // Several error may come out with file handling or DOM
            e.printStackTrace();
        }
    }



    //Function to share Screenshot
    private void shareScreenshots(File file){
        Uri uri = Uri.fromFile(file);
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("image/*");

        intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
        intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        try {
            startActivity(Intent.createChooser(intent, "Share Screenshot"));
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, "No App Available", Toast.LENGTH_SHORT).show();
        }
    }

    //Function to open screenshot
    private void openScreenshot(File imageFile) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        Uri uri = Uri.fromFile(imageFile);
        intent.setDataAndType(uri, "image/*");
        startActivity(intent);
    }

此方法不需要存储和检索屏幕截图以再次共享。 在方法调用上,您将能够共享屏幕截图。

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 void share(Bitmap bitmap){
    String pathofBmp=
            MediaStore.Images.Media.insertImage(ctx.getContentResolver(),
                    bitmap,"title", null);
    Uri uri = Uri.parse(pathofBmp);
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType("image/*");
    shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Star App");
    shareIntent.putExtra(Intent.EXTRA_TEXT, "");
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    ctx.startActivity(Intent.createChooser(shareIntent, "hello hello"));
}

像这样调用这个方法

share(screenShot(view));

在没有读写权限的情况下使用此直接共享屏幕截图

截至 2021 年,这里是完整的答案,您只需复制这段代码,它应该可以正常工作,而且它使用所有新的 API,包括许可启动器,以及 android q 保存图像的方式
我将再添加一项功能,即像这样在图片文件夹中保存内部文件夹

/Pictures/MyAppName/photos.png

此代码还支持 android < 10 以及更新的代码。

我正在拍摄屏幕并将其保存到桌面以获取图像的 uri,以便稍后共享。

首先,android < 10

需要权限启动器
val requestStoragePermissionLauncher =
    registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        var saveImageFlag = true
        permissions.entries.forEach {
            saveImageFlag = it.value
        }
        if (saveImageFlag) {
            shareScreenShootResult()
        } else {
            showMessage(getString(R.string.cant_share_ScreenShoot))
        }
    }

val permissionListener: () -> Boolean = {
    if (ContextCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.READ_EXTERNAL_STORAGE
        ) == PackageManager.PERMISSION_GRANTED &&
        ContextCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        true
    } else {
        requestStoragePermissionLauncher.launch(
            arrayOf(
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            )
        )
        false
    }
}

然后下一个方法给出图片名称并设置目录然后分享图片

private fun shareScreenShootResult() {
    val dateFormatter by lazy {
        SimpleDateFormat(
            "yyyy.MM.dd 'at' HH:mm:ss z", Locale.getDefault()
        )
    }
    val filename = "${getString(R.string.my_ScreenShoot)}${dateFormatter.format(Date())}.png"
    val ScreenShootFolderPath = File.separator + requireContext().getAppName()

    val uri = binding.rootLayout.makeScreenShot()
        .saveScreenShot(requireContext(), filename, ScreenShootFolderPath, permissionListener)
        ?: return

    dispatchShareImageIntent(uri)
}

private fun dispatchShareImageIntent(screenShotUri: Uri) {
    val intent = Intent(Intent.ACTION_SEND)
    intent.type = "image/png"
    intent.putExtra(Intent.EXTRA_STREAM, screenShotUri)
    startActivity(Intent.createChooser(intent, "Share"))
}

getAppName 是一个扩展函数,你可以在项目的任何地方添加它,然后在上下文中调用它,不要忘记导入它。

fun Context.getAppName(): String {
    var appName: String = ""
    val applicationInfo = applicationInfo
    val stringId = applicationInfo.labelRes
    appName = if (stringId == 0) {
        applicationInfo.nonLocalizedLabel.toString()
    } else {
        getString(stringId)
    }
    return appName
}

此方法makeScreenShot是View上的扩展函数 你最好在不同的文件中添加所有扩展函数。

fun View.makeScreenShot(): Bitmap {
    setBackgroundColor(Color.WHITE)
    val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    draw(canvas)
    return bitmap
}

它 returns 我正在调用的位图 saveScreenShot 这是另一个扩展函数

fun Bitmap.saveScreenShot(
    requireContext: Context,
    filename: String,
    ScreenShootFolderPath: String,
    permissionListener: () -> Boolean,
): Uri? {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
        saveImageInQ(this, filename, ScreenShootFolderPath, requireContext.contentResolver)
    else
        legacySave(this, filename, ScreenShootFolderPath, permissionListener)
}

private fun saveImageInQ(
    bitmap: Bitmap,
    filename: String,
    parentFileName: String,
    contentResolver: ContentResolver
): Uri? {
    val fos: OutputStream?
    val uri: Uri?
    val contentValues = ContentValues()
    contentValues.apply {
        put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
        put(MediaStore.Files.FileColumns.MIME_TYPE, "image/png")
        put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + parentFileName)
        put(MediaStore.MediaColumns.IS_PENDING, 1)
    }

    uri =
        contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
    uri?.let { contentResolver.openOutputStream(it) }.also { fos = it }

    fos?.use { bitmap.compress(Bitmap.CompressFormat.PNG, 100, it) }
    fos?.flush()
    fos?.close()

    contentValues.clear()
    contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
    uri?.let {
        contentResolver.update(it, contentValues, null, null)
    }
    return uri
}

private fun legacySave(
    bitmap: Bitmap,
    filename: String,
    parentFileName: String,
    permissionListener: () -> Boolean,
): Uri? {
    val fos: OutputStream?
    if (!permissionListener()) {
        return null
    }

    val path =
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() +
                parentFileName + File.separator + filename
    val imageFile = File(path)
    if (imageFile.parentFile?.exists() == false) {
        imageFile.parentFile?.mkdir()
    }
    imageFile.createNewFile()
    fos = FileOutputStream(imageFile)
    val uri: Uri = Uri.fromFile(imageFile)

    fos.use { bitmap.compress(Bitmap.CompressFormat.PNG, 100, it) }
    fos.flush()
    fos.close()

    return uri
}

创建帮助程序 class 以创建和共享屏幕截图

public class share {
private final Context c;
public share(Context c) {
    this.c = c;
}
public void shareInt(Bitmap bitmap, String msg, String name) {
    Uri uri = getmageToShare(bitmap, name);
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.putExtra(Intent.EXTRA_STREAM, uri);
    intent.putExtra(Intent.EXTRA_TEXT, msg);
    intent.setType("*/*");
    c.startActivity(Intent.createChooser(intent, "Share Via").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}

// Retrieving the url to share
private Uri getmageToShare(Bitmap bitmap, String name) {
    File imagefolder = new File(c.getCacheDir(), "images");
    Uri uri = null;
    try {
        imagefolder.mkdirs();
        File file = new File(imagefolder, name+".png");
        FileOutputStream outputStream = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 70, outputStream);
        outputStream.flush();
        outputStream.close();
        uri = FileProvider.getUriForFile(c, "com.yourapp.fileprovider", file);
    } catch (Exception e) {
        Toast.makeText(c, "" + e.getMessage(), Toast.LENGTH_LONG).show();
    }
    return uri;
   }
}

现在从任何 activity 想要截屏和分享的地方调用此助手 class

CardView mainView = findViewById(R.id.mainView);
new share(c).shareInt(new getBitmap().screenShot(mainView), "msg", "randomstring");

这里的mainView就是你要抓拍的视图,jzt传递视图参考。

不需要运行时间许可,因为我们正在使用缓存目录