3

Recently I found some apps (which I already installed) have been removed from Google Play Store for different reasons according to Google.

Is there a way to get notified about removed apps from the Play Store, like some app to check currently installed apps, whatever (special) newsletter/feed for this or any other way?

2
  • 1
    Are you open to get your hands a bit dirty? AFAIK, a Play Store user officially cannot come to know why an app was removed from Play Store. Only the developer of the app would be privy to this information. The only way we can know that an app doesn't exist is by visiting its page. If the app doesn't exist, server would return 404 HTTP code. We can use tasker to query the URL (containing an installed app's package name) and match the returned HTTP code. If 404, notify user the way you want. You can run this query every day or after any number of hours/days.
    – Firelord
    Jan 21, 2016 at 20:09
  • 1
    @Firelord that would require a quite complex task to setup in Tasker (but gives me a nice idea for a new feature in Adebar – see github.com/IzzySoft/Adebar/issues/17 ;) One would have to gather package names for all user-installed apps, query the corresponding playstore pages and, whenever a 404 pops up, perform "some action" (notification plus something more permanent in case of device reboot etc). Be welcome to setup such an answer :)
    – Izzy
    Jan 22, 2016 at 12:33

1 Answer 1

10

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. Variables → Variable Split

    • Name: %Tmp

    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.

  7. Variables → Variable Split

    • Name: %Tmp1
    • Splitter: :

    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.

  8. 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.

  9. 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.

  10. Variables → Variable Subtract

    • Name: %Count
    • Value: 1

    This step decrements Count variable so that we can move to next cycle of loop.

  11. 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)

IMG:

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:

  1. 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.

  2. Task → If: %Pkgs Set

  3. 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:

IMG:

1
  • Thanks @Firelord for the detailed Tasker procedure. Worked like a charm. Had to make some minor tweaks to align with changes in the current Tasker app - I have edited your post. Also the HTTP Get action has been deprecated and replaced with HTTP Request, but still works. I wanted to supply the XML code here but the formatter doesn't accept it all, even when within a preformatted text block)
    – Joe Soap
    Aug 30, 2019 at 19:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .