Take screen shot of any screen - android

I am using the following code to take screen shot of current activity:
View rootview = findViewById(android.R.id.content).getRootView();
rootview.setDrawingCacheEnabled(true);
And save the image on the SD card.
But I am trying to take a screenshot of not just this app, but outside this app as well, I have done some research and found that it's possible only with ROOTED devices, but is there any way that we can take a screen shot of any screen without rooting the device?

Try using reflection to call takeScreenshot() from PhoneWindowManager.java Refer to this link
Refer the following code from here
Do this for PhoneWindowManger.
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
try {
Log.v(TAG, "Get getTeleService...");
Class c = Class.forName(telephony.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(telephony);
telephonyService.silenceRinger();
Log.v(TAG, "Answering Call now...");
telephonyService.answerRingingCall();
Log.v(TAG, "Call answered...");
//telephonyService.endCall();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG,
"FATAL ERROR: could not connect to telephony subsystem");
Log.e(TAG, "Exception object: " + e);
}
Android L offers APIs to capture screenshot.refer-https://developer.android.com/reference/android/media/projection/package-summary.html

You are interested in the READ_FRAME_BUFFER permission: http://developer.android.com/reference/android/Manifest.permission.html#READ_FRAME_BUFFER
Problem is that it clearly states: "Not for use by third-party applications."
You are out of luck. This is a security feature (not allowing any app to take screenshots of other apps) that won't go away. You will be limited to rooted devices.

Here is the code that allowed my screen shot to be stored on sd card and used later for whatever your needs are:
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + ACCUWX.IMAGE_APPEND;
// create bitmap screen capture
Bitmap bitmap;
View v1 = mCurrentUrlMask.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
OutputStream fout = null;
imageFile = new File(mPath);
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Then, when you need to access use something like this:
Uri uri = Uri.fromFile(new File(mPath));

Depends on your purpose. If you need that feature in your application which distributed to playstore, you don't have luck. Without root permission, it's simply not possible.
For test or personal purpose, however, adb will help. You just send
some packet to your machine's adb server, you can retrieve device's screen shot.
To do that, you should read out adb client <-> server protocol. framebuffer protocol seems perfect to you.
Or If you familiar with node.js, adbkit will save your time.

Android L offers APIs to capture screenshot.refer-https://developer.android.com/reference/android/media/projection/package-summary.html

Related

how to get my app write on Sd card with Oreo

I have a strange problem writing on my external sd card running Android Oreo :
First the usual commands
getExternalFilesDir(null).getAbsolutePath()
or
Environment.getExternalStorageDirectory().getAbsolutePath()
return the path to the emulated storage not the real sd card sometimes called secondary external storage.
But well that's not the issue as I manage to get the path to the SD card using the method getExternalStoragePath() described at the end of my post.
Now the strange thing is that I cannot get my app (let's say the package is com.example.myapp) creating the directory
SDCARDPATH/Android/data/com.example.myapp/files
despite all necessary authorizations have been properly granted (but it is possible that the WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE apply only to the emulated storage, I have a feeling that the issue is there!) Here is what I'm doing :
String SDCARDPATH=getExternalStoragePath(this, true);
File md = new File(new File(new File(new File(SDCARDPATH,"Android"),"data"),PACKAGE_NAME),"files");
if(!md.exists()) {
try {
md.mkdirs();
} catch (Exception e) {
e.printStackTrace();
}
}
The strange thing is that if I create the directory manually through the phone file explorer the app can then write and read within that directory without any trouble.
So my question is how to properly create that directory on my external sdcard
Side note I see some app installed on my phone have managed to create their app directory on the sd card.
Finally here is the getExternalStoragePath method I use and which was grabbed on the net :
Thanks to all in advance for your help,
Lea
public static String getExternalStoragePath(Context mContext, boolean is_removable) {
StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz = null;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
Object result = getVolumeList.invoke(mStorageManager);
final int length = Array.getLength(result);
for (int i = 0; i < length; i++) {
Object storageVolumeElement = Array.get(result, i);
String path = (String) getPath.invoke(storageVolumeElement);
boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
if (is_removable == removable) {
return path;
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
I manage to get the path to the SD card using the method getExternalStoragePath() described at the end of my post
That code is not going to work on all versions of Android. In particular, it will not work on Android 10+. I would not be the least bit surprised if it fails on Android 9.0 as well, given that it relies upon reflection into system classes. It will also fail on older devices where those classes and methods do not exist.
First the usual commands getExternalFilesDir(null).getAbsolutePath() or Environment.getExternalStorageDirectory().getAbsolutePath() return the path to the emulated storage not the real sd card sometimes called secondary external storage
Use getExternalFilesDirs() (note the s at the end). That returns a File[]. If that array has 2+ elements, all but the first element point to directories on removable storage that you can use from your app, without any permissions. The directory should already be created, but you can call mkdirs() on the File to ensure that it exists.

Take screenshot of current showing screen, NOT the current activity

I'm trying to make a little Android app that triggers a screenshot capture of the current showing screen when a specific notification appears. For example, I'm on whatsapp and a Whatsapp notification appears -> That triggers a whatsapp capture.
Well, my current code actually detects notifications and triggers a screenshot when a notification comes, but not the way I want. I get a screenshot of my MainActivity, even if it's not showing on the screen. I just want to screenshot what it's appearing on the screen. It seems easy but I'm not being able to do it!
I leave my current NotificationReceiver class, which is failing because it captures the MainActivity and not the screen:
class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String temp = intent.getStringExtra("notification_event") + "\n" + txtView.getText();
txtView.setText(temp);
if (intent.getStringExtra("notification_event").contains("bet")) {
Log.i("Dentro", "dentro");
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";
// 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();
} catch (Throwable e) {
// Several error may come out with file handling or OOM
Log.i("Catch","Error dentro del if(contains)");
e.printStackTrace();
}
}//fin if
}
}
Any ideas of how can I proceed? I'm actually stuck. Help would be really appreciated!
You would need to use the media projection APIs on Android 5.0+, and set your minSdkVersion to 21. For privacy and security reasons, apps cannot take screenshots of other apps without explicit user permission, and that only became possible with Android 5.0.
This sample app demonstrates taking screenshots on demand.

Proper way to share an Image (using Intents)

I create images in my app and want to share these social networks (facebook), mail apps (gmail), and other apps that can "receive" images.
The origin of the problem (I think) is that I don't want to use the external storage as a base for my images. I want to either use my data folder or my cache folder since neither of these require any permission to access.
The code which I use to write my image to file (and I specify the MODE_WORLD_READABLE so that other apps can read them):
FileOutputStream fos = null;
try {
fos = context.openFileOutput("image.jpg", Context.MODE_WORLD_READABLE);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} finally {
if (fos != null)
fos.close();
}
And this is the code where I share the image:
File internalFile = context.getFileStreamPath("image.jpg");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(internalFile));
intent.setType("image/jpeg");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(intent, "share"));
This solution is very easy and works fine for apps like facebook but not for example gmail which failes with:
file:// attachment paths must point to file:///mnt/sdcard
There are a number of "hacks" (see below) to get it to work with gmail but I leaves me asking myself if there is an even better way to share images that works without hacks, something I overlooked. So, to the questions:
What is the best way to share images? (external storage?)
Is there any more apps that (mis-)behave just like gmail? (I have seen some trouble with google+)
If there is no other way: Can I write special intents for sharing to specific apps. I have a default way of sharing and override it when the user selects an app on my watch list?
Hacks
Using a path-hack by simply pointing the Uri to:
file:///mnt/sdcard/../../my/package/name/...
This solution doesn't feel right.
Using a ContentProvider as described here. But quoted from the link:
Warning: the method described in the post works well for Gmail, but apparently has some issues with other ACTION_SEND handlers (e.g. the MMS composer).
(Issue: It crashes the MMS composer)
Did you try ParecelableFileDescriptor?
http://developer.android.com/reference/android/os/ParcelFileDescriptor.html
Create with
static ParcelFileDescriptor open(File file, int mode, Handler handler, ParcelFileDescriptor.OnCloseListener listener)
Create a new ParcelFileDescriptor accessing a given file.
static ParcelFileDescriptor open(File file, int mode)
Create a new ParcelFileDescriptor accessing a given file.
Receiver side like this:
Returning an Input Stream from Parcel File Descriptor using Androids DownloadManager
You should to make 3 steps.
Take picture.
public Bitmap takeScreenshot() {
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
Save picture.
public String saveBitmap(Bitmap bitmap) {
File imagePath = new File(Environment.getExternalStorageDirectory() + “/screenshot.png”);
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e(“GREC”, e.getMessage(), e);
} catch (IOException e) {
Log.e(“GREC”, e.getMessage(), e);
}
return imagePath.getAbsolutePath();
}
Share to social network.

Android bitmap in path

I am wondering how to get the bitmap from specific location as follows:
try {
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL("C:/java/AVMOrderServer/files/main_ads/fff.jpg").getContent());
iv.setImageBitmap(bitmap);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Any advice would be useful (I found the code sample on stackoverflow which is an answer voted as true)
Thank you all.
Your Android device does not have a C drive, that's generally a DOS/Windows concept. Android is based on Linux. If you want to view a bitmap on your computer from your Android device you'll have to copy it over first, whether by including it in your APK or by copying to SD card.

Android - how to set the wallpaper image

Is it possible to set the android wallpaper image programatically? I'd like to create a service that downloads an image from the web and updates the home screen wallpaper periodically.
If you have image URL then use
WallpaperManager wpm = WallpaperManager.getInstance(context);
InputStream ins = new URL("absolute/path/of/image").openStream();
wpm.setStream(ins);
If you have image URI then use
WallpaperManager wpm = WallpaperManager.getInstance(context);
wpm.setResource(Uri.of.image);
In your manifest file:
<uses-permission android:name="android.permission.SET_WALLPAPER"></uses-permission>
From this page on the developer site:
public void setStream (InputStream data)
Change the current system wallpaper to a specific byte stream. The give InputStream is copied into persistent storage and will now be used as the wallpaper. Currently it must be either a JPEG or PNG image.
If you have bitmap of image than you will add this function to set as wallpaper:
public void SetBackground(int Url) {
try {
File file = new File("/sdcard/sampleimage");
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), Url);
bitmap.compress(CompressFormat.JPEG, 80, new FileOutputStream(file));
Context context = this.getBaseContext();
context.setWallpaper(bitmap);
Toast.makeText(getApplicationContext(), "Wallpaper has been set", Toast.LENGTH_SHORT).show();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
you should add permission for this
<uses-permission android:name="android.permission.SET_WALLPAPER"></uses-permission>
hope it will work
OK Here's how to do it before api 2.0:
You need to call getApplicationContext.setWallpaper() and pass it the bitmap.
This method is now deprecated. See ChrisF's answer for details on the new method.

Categories

Resources