2015-05-12 2 views
22

Мне нужно сделать снимок экрана Activity (без заголовка, и пользователь НЕ должен видеть, что снимок экрана фактически был снят), а затем поделитесь им с помощью кнопки меню действий «поделиться». Я уже пробовал некоторые решения, но они не работали для меня. Есть идеи?Как сделать снимок экрана текущей деятельности, а затем поделиться ею?

+1

попробовать [это] (http://stackoverflow.com/questions/21228239/android-capture-screenshot-programmatically-without-title-bar) – dora

+0

@dora это не идеальное решение для меня, потому что оно использует макеты, и я не хочу ничего делать, кроме как снимать снимок экрана. –

+0

В любом случае вы будете захватывать представление. Либо через xml-макет, либо программно созданный макет. Дора прав. – SmulianJulian

ответ

64

Вот как я захватил экран и поделился им. Посмотрите, если вы заинтересованы.

Первый, получить вид корня из текущей деятельности:

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

Я надеюсь, что вы будете вдохновлены моими кодами.

UPDATE:

Добавить ниже разрешений на Ваш AndroidManifest.xml:

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

Поскольку он создает и получает доступ к файлам во внешнем хранилище.

UPDATE:

Начиная с Android 7.0 нуга ссылок на файлы обмена являются использованы без разрешения. Чтобы справиться с этим, вам нужно реализовать FileProvider и поделиться «content: //« uri not »file: //« uri.

Here - хорошее описание, как это сделать.

+0

его снимок экрана, но не показывая в галерее, когда я проверяю хранение устройства, есть файлы скриншотов, но когда я пытаюсь щелкнуть их, он говорит, что не может найти приложение, чтобы открыть этот файл. –

+0

Этого не может быть. Catch' ActivityNotFoundException' из 'startActivity (Intent.createChooser (намерение,« Share Screenshot »));' и после этого 'Toast.makeText (контекст,« Нет приложения », Toast.LENGTH_SHORT) .show();'. – SilentKnight

+2

java.io.FileNotFoundException:/storage/emulated/0/Скриншоты/изображение: open failed: ENOENT (Нет такого файла или каталога) –

4

Вы можете использовать нижеследующий код, чтобы получить растровое изображение для просмотра, которое вы видите на экране. Вы можете указать, какой вид создать растровое изображение.

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

Вы можете сделать снимок экрана с любой части вашего вида. Вам просто нужна ссылка на макет, на который вы хотите сделать снимок экрана. например, в вашем случае вы хотите снять снимок вашей активности. допустим, что ваш корневой каталог активности - это линейная компоновка.

// 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; 
     } 
3

Я не мог заставить Silent Knight's answer работать, чтобы работать, пока я не добавил

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

моему AndroidManifest.xml.

0

Вот как я захватил экран и поделился им. Посмотрите, если вы заинтересованы.

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

6

создать кнопку поделиться с нажатием на слушателя

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

Add два метода

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

Share screen shot. совместного осуществления здесь

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")); 
    } 
+1

Это хорошая кодировка! –

+1

Чистый и элегантный ответ :) – ch3tanz

+0

Спасибо :) # ch3tanz –

0

Для всех Xamarin пользователей:

Xamarin.Android Код:

Создание внешнего класса (у меня есть интерфейс для каждая платформа, и я реализовал эти 3 функции ниже с платформы Android):

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

Теперь от вашей деятельности, вы запустите приведенный выше код следующим образом:

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

Надеется, что это будет полезно для всех.

1

для съемки экрана

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

Это то, что я использую, чтобы сделать снимок экрана. Описанные выше решения отлично работают для 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> 
Смежные вопросы