The whole answer relies on the fact that when this query is made:
https://play.google.com/store/apps/details?id=PKG_NAME # PKG_NAME is the package name of an app
among other things, the HTTP code in the returned headers in most of the cases would either be:
- 404 (resource not found) - app not available
- 200 (success) - app available
- 403 (forbidden) - app not available in your region or you're not authorized to access the resource
I've used the said information in the two solutions proposed here.
Automation
I found Tasker (user guide) apt as well as flexible for the job. Details on trigger i.e. Profile would follow later. For the time being, follow these instructions for the core.
Create a task named App Status and create the following actions in it:
Code→ Run Shell
- Command:
pm list packages -3 -i | grep -e "com.android.vending" -e "com.google.android.feedback"
- Store Output In:
%Pkgs
- select Continue Task After Error
This will store the list of all the apps' package names installed from Play Store, into variable Pkgs. Remove
-i | grep -e "com.android.vending" -e "com.google.android.feedback"
from Command if you don't want to restrict the task to apps installed only from Play Store.
Variables → Variable Set
- Name:
%ret
- To: tap Enter key in your keyboard for once
I learned this step from the post here by plepleus. This step is needed because we intend to copy each line (has a package name of an app) from Pkgs into a separate variable. It is for ease of use.
Variables → Variable Split
- Name:
%Pkgs
- Splitter:
%ret
This step splits Pkgs, makes an array of Pkgs and each line is assigned to an index of that array. Hence, the size of the array is the number of lines Pkgs had.
Variables → Variable Set
- Name:
%Count
- To:
%Pkgs(#)
We're creating a variable named Count and assigning it the length of Pkgs array, for the purpose of looping.
Variables → Variable Set
- Name:
%Tmp
- To:
%Pkgs(%Count)
Now that we're in a loop, we're storing the value assigned to a Pkgs's index into a new variable named Tmp. This step is needed because Tasker has limited functionality when dealing with complex variable names.
Variables → Variable Split
This step splits the line at whitespace and store the preceding and succeeding fields into Tmp1 and Tmp2. Tmp1 contains the package name among other things.
Variables → Variable Split
This step finally extracts the package name from Tmp1 and stores it into Tmp12. Note that if Tmp was not declared in action 5, we would have been forced to split %Pkgs(%Count)1 which is an invalid variable name for Tasker.
Net → HTTP Get
- Server:Port:
https://play.google.com/store/apps/details?id=%Tmp12
- Mime Type:
text/html
- select Continue Task After Error
This step queries the status of the app in Play Store and saves the returned HTTP code automatically in HTTPR.
App → Test App
- Type: App Name
- Data:
%Tmp12
- Store Result In:
%Label
- select Continue Task After Error
This step finds the app's label from its package name and stores it in Label.
Variables → Variable Subtract
This step decrements Count variable so that we can move to next cycle of loop.
Task → Goto
- Type: Action Number
- Number:
5
- If:
%Count
!=
0
This step finally implements the loop. When this action is executed it checks whether Count is 0 or not. We've assumed that all lines in Pkgs had package name so it amounts to reason loop should run until Count becomes zero, in which case, simply exit.
How you would like to be notified is I leave upon you to decide. Whatever you intended to do for the purpose of notifying yourself the status of an app in Play Store, do it only between action 9 and 10. As an example, you can setup App Status task to show a notification when an app is not found in Play Store. You can add the action: Alert → Notify:
- Title: Play Store: App not available
- Text: %Label
- Priority: 5
- If:
%HTTPR
eq
404
You can use AutoNotifications to get around the Tasker's limited functionality of creating notifications.
Considering that a reboot causes loss of all received notifications, you can write the final output of the task into a file. Use the action File → Write File and use it in append mode. That's just an advice per Izzy's comment on the question. I won't be able to offer any help in this regard.
As for the Profile, choose any number of triggers you want. I recommend a time based trigger, but you can also opt to create a shortcut on home screen.
That's all for automation here.
Command-line
I couldn't ignore command-line which makes the objective so easy to be achieved in this particular case.
Dependencies
- Requires busybox binary. If you don't have it installed, refer to: How do I install missing command line tools onto an Android device?
Requires aapt binary. If you're running a CM or its derivative ROM then ignore this requirement. Otherwise, for Android 4.x, you can consider downloading the binary from here. For the purpose of installing it in device, follow the root or non-root approach mentioned here, appropriately.
Android 5.x users: ask Google for assistance.
My little script
#!/system/bin/sh
# Check if the busybox binary exists under /data/local/tmp/ or /system/xbin.
# Set the detected binary's path into the variable busybox or exit if file
# doesn't exist or executable permission is not set
if [[ -x /data/local/tmp/busybox ]]; then
busybox=/data/local/tmp/busybox;
elif [[ -x /system/xbin/busybox ]]; then
busybox=/system/xbin/busybox;
else
date +'busybox binary not found or executable permission is not set. Exiting';
exit;
fi
# Check if the aapt binary exists under /data/local/tmp or /system/bin or /system/xbin.
# Set the detected binary's path into the variable aapt or exit if file
# doesn't exist or executable permission is not set
if [[ -x /data/local/tmp/aapt ]]; then
aapt=/data/local/tmp/aapt;
elif [[ -x /system/bin/aapt ]]; then
aapt=/system/bin/aapt;
elif [[ -x /system/xbin/aapt ]]; then
aapt=/system/xbin/aapt;
else
date +'aapt binary not found or executable permission is not set. Exiting';
exit;
fi
# List packages which were installed from Play Store and store the package names under /sdcard/acc_assoc_packages.txt.
# Remove -i | grep -e "com.android.vending" -e "com.google.android.feedback" if you don't want to restrict the script to apps installed only from Play Store.
pm list packages -3 -i | grep -e "com.android.vending" -e "com.google.android.feedback" | $busybox sed 's/package://g'| $busybox awk '{print$1}' > /sdcard/acc_assoc_packages.txt
$busybox printf "List of installed apps not available in Play Store:\n\n" > /sdcard/rm_packages.txt; # rm_packages.txt would show the list of apps not available in Play Store
# For each package name in acc_assoc_packages.txt, find whether the package is available in Play Store.
# If not, the HTTP return code would be 404 in curl's output. Use it for any processing you want.
while read line; do
ID="https://play.google.com/store/apps/details?id=";
ret_http_code=$(curl -skI $ID$line | awk 'FNR==1{print $2}'); # -s is for silent mode, -k is use ignore certificates for SSL connection, -I is to show only header information
path=$(pm path $line | $busybox sed 's/^package://g'); # get location of APK of package. Required for finding app's label
label=$($aapt d badging $path 2>&1 | $busybox sed -ne '/application: label=/p' | $busybox cut -d "'" -f2); # Get app label using $path
# If returned HTTP code is 404, write into rm_pacakges.txt the corresponding app label, package name and print to standard output.
# Else simply print to standard output.
case $ret_http_code in
404)
$busybox printf "Status: Not Available - $label ($line)\n";
$busybox printf "$label ($line)\n" >> /sdcard/rm_packages.txt;
;;
403)
$busybox printf "Status: Not authorized to access resource - $label ($line)\n";
;;
200)
$busybox printf "Status: Available - $label ($line)\n";
;;
*)
$busybox printf "An unknown error occurred. Are we online?\n";
exit;
esac
done < /sdcard/acc_assoc_packages.txt
Save the script under /sdcard
into a file named app_status.sh
and run that file from a terminal emulator app in this manner:
sh /sdcard/app_status.sh
Demo output:
(Click image to enlarge)

Shortcut
If you've busybox and aapt binary installed and working in device, you can drastically reduce the steps needs in App Status task.
Store the following script into a file named app_status.sh
under /sdcard
.
#!/system/bin/sh
pm list packages -3 -i | grep -e "com.android.vending" -e "com.google.android.feedback" | $busybox sed 's/package://g'| $busybox awk '{print$1}' > /sdcard/acc_assoc_packages.txt
$busybox printf "List of installed apps not available in Play Store:\n\n" > /sdcard/rm_packages.txt;
while read line; do
ID="https://play.google.com/store/apps/details?id=";
ret_http_code=$(curl -skI $ID$line | awk 'FNR==1{print $2}');
path=$(pm path $line | $busybox sed 's/^package://g');
label=$($aapt d badging $path 2>&1 | $busybox sed -ne '/application: label=/p' | $busybox cut -d "'" -f2);
case $ret_http_code in
404)
$busybox printf "Status: Not Available - $label ($line)\n";
$busybox printf "$label ($line)\n" >> /sdcard/rm_packages.txt;
;;
403|200)
# Intentionally left blank
;;
*)
$busybox printf "An unknown error occurred. We'll be victorious next time.\n" >> /sdcard/rm_packages.txt;
exit;
esac
done < /sdcard/acc_assoc_packages.txt
Now delete any action you have in the task and setup the following ones:
Code → Run Shell
- Command:
sh /sdcard/app_status.sh
- Store Output In:
%Pkgs
- select Continue Task After Error
This step will write into file rm_packages.txt the entries as the apps not available in Play Store. This is the core action. The following actions are optional and meant only for the purpose of notifying yourself.
Task → If: %Pkgs
Set
Alert → Notify
- Title: Check apps' status
- Icon: optional
- Priority:
5
- Actions: Action → App → Launch App → select a text editor app such as QuickEdit → Data:
file:///sdcard/rm_packages.txt
Example notification:
