Detect if another app is requesting the microphone

2019-05-25 02:35发布

I have seen multiple questions on SO that say it is impossible to see when another app wants to use the microphone (Unable to access microphone when another app is using it in Android). However, I know it is possible because Shazam has an "Auto" function that allows the exact functionality I want: to continuously listen to audio when other apps are not using the microphone.

Currently, when I use my app and use an app like Snapchat, I am unable to record a video with audio because Snapchat does not take the mic over. However, as I said before, in this case Shazam's Auto feature works fine.

So how do I listen for when other apps want to use the mic? I am fine using something that is a "hack" as long as it does not require rooting the phone or similar.

EDIT: Shazam never had this functionality, their app fails to relinquish the mic to other applications while it is running.

1条回答
狗以群分
2楼-- · 2019-05-25 02:56

This is currently the best solution I have. There is no way to listen for other applications requesting the microphone, so I created a UsageStats checker that runs every 3 seconds to see if the currently open app has the ability to request audio. Please let me know if you have something better or make improvements to this.

Note: You must add the permissions to the app manifest:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />

    AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
    int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
            android.os.Process.myUid(), getPackageName());

    if (mode != AppOpsManager.MODE_ALLOWED) {
        Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
        startActivity(intent);
    }

    if (otherAppAudioTimer != null) {
        otherAppAudioTimer.cancel();
    }

    otherAppAudioTimer = new Timer();
    otherAppAudioTimer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            UsageStatsManager usm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
            long now = System.currentTimeMillis();
            final List<UsageStats> queryUsageStats = usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, now - (1000 * 60 * 60), now);
            if (queryUsageStats != null && queryUsageStats.size() > 0) {
                SortedMap<Long, UsageStats> mySortedMap = new TreeMap<>();
                for (UsageStats usageStats : queryUsageStats) {
                    mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
                }
                if (!mySortedMap.isEmpty()) {
                    String currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
                    boolean hasRecordAudio = getPackageManager()
                            .checkPermission(Manifest.permission.RECORD_AUDIO, currentApp)
                            == PackageManager.PERMISSION_GRANTED;

                    if (getApplicationContext().getPackageName().equals(currentApp)) {
                        Log.e("hasAudio", "Current app is self");
                        return;
                    }


                    if (hasRecordAudio) {
                        //the current app can record audio
                    } else {
                        //the current app cannot record audio
                    }

                }
            }
        }
    }, 0, 3000);
查看更多
登录 后发表回答