I'm really just wondering about how such a functionality can be implemented, for pure curiosity about software design.

In particular, if the OS offers a way to show an image and a way to take a screenshot, how can a messaging app (such as WhatsApp) know that a screenshot is being taken while an image is being show, and deny the screenshot accordingly?


Below are my lucubrations about the matter and my attempt to imagine how such an interaction could happen (I used a C++-like syntax just because I know C++ better than other languages).

I would assume that the OS provides a function like this to show an image

namespace os {
void showImage(Image* i, bool allowScreenshot = true/*default*/) {
    screenshotAllowed/* this is a global state of the phone */ = allowScreenshot;
    showImageImpl(i);
}
}

and one like this to take screenshots

namespace os {
void takeScreenshot() /* called when 3-finger swiping, for instance */ {
    if (!screenshotAllowed)
        return;
    takeScreenshotImpl();
}
}

This way I would assume that the messaging app, if it doesn't provide a feature akin to WhatsApp's "View Once", has a function for opening the image like this,

namespace msgapp {
void showImage(Image* i) /* called when opening any image message */ {
    os::showImage(i);
}
}

whereas if does provide it (or when it is upgraded to provide it) another overload is exposed

namespace msgapp {
struct ViewOnceImage : Image {};
void showImage(ViewOnceImage* i) /* called when opening a view-once image message */ {
    os::showImage(i, false);
}
}
2

There are 2 best solutions below

0
Gabe Sechan On

On Android you can register a window as secure- meaning you're showing private information. This will prevent the OS from taking a screenshot or displaying the contents in the recents apps. Of course nothing stops them from taking a photo with another phone. Or using a customized OS that ignores that flag. So I wouldn't treat it as totally secure, just more likely to be secure- it takes a tiny bit of effort/inconvenience to work around. Marking it as secure is a window flag set prior to display,via getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);

0
Kashan Danish On

Mobile operating systems don't provide an API to show images. It is the apps themselves that display the images. So instead of os::showImage(i), it would be something like

currentScreen.imageContainer.loadImageFromUrl(image.url)

On disabling screenshots, Android provides a way for the apps to specify when they are displaying sensitive content and the OS disables screenshot functionality. Similarly, there are APIs to detect when a screenshot is taken if the screenshot functionality is not disabled

On displaying image only once, this can be done in multiple ways, while I am not 100% sure how WhatsApp is doing it, my guess would be they are using a local database to store image-viewed status. At a very simplified level, it would be something like this

if (!image.isDisplayed) {
    currentScreen.imageContainer.loadImageFromUrl(image.url)
    image.isDisplayed = true
} else {
    currentScreen.imageContainer.loadImageFromUri(placeholderImage.uri)
}

In addition to this, maybe they are deleting the locally cached image and making an API call to the server to invalidate the image URL as well.

But all these functionalities (displaying images, preventing images from being shown more than once, disabling screenshots, and letting users know when a screenshot is being taken) all have separate independent mechanisms.