내장 된 응용 프로그램 (메시징, 연락처 등)이 언제 실행되고 있는지 알 수있는 백그라운드에서 실행되는 하나의 응용 프로그램을 갖고 싶습니다.
그래서 내 질문은 다음과 같습니다.
-
애플리케이션을 백그라운드에서 실행하는 방법.
-
내 백그라운드 애플리케이션이 현재 포 그라운드에서 실행중인 애플리케이션이 무엇인지 알 수있는 방법.
경험이 많은 분들의 답변 부탁드립니다.
답변
“2. 내 백그라운드 애플리케이션이 현재 포 그라운드에서 실행중인 애플리케이션이 무엇인지 알 수있는 방법”과 관련하여.
getRunningAppProcesses()
내 경험에서 모든 종류의 시스템 쓰레기를 반환 하므로 메서드를 사용하지 마십시오 RunningAppProcessInfo.IMPORTANCE_FOREGROUND
. 사용 getRunningTasks()
하는 대신
이것은 현재 포 그라운드 애플리케이션을 식별하기 위해 서비스에서 사용하는 코드입니다. 정말 쉽습니다.
ActivityManager am = (ActivityManager) AppService.this.getSystemService(ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
이제 포 그라운드 앱 / 활동의 세부 정보에 쉽게 액세스 할 수 있습니다.
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
PackageManager pm = AppService.this.getPackageManager();
PackageInfo foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
String foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();
이것은 활동 메니 페스트에 대한 추가 권한이 필요하며 완벽하게 작동합니다.
<uses-permission android:name="android.permission.GET_TASKS" />
답변
어려운 방법으로 올바른 솔루션을 찾아야했습니다. 아래 코드는 cyanogenmod7 (태블릿 조정)의 일부이며 Android 2.3.3 / gingerbread에서 테스트되었습니다.
행동 양식:
- getForegroundApp-포 그라운드 애플리케이션을 반환합니다.
- getActivityForApp-찾은 앱의 활동을 반환합니다.
- isStillActive-이전에 찾은 앱이 여전히 활성 앱인지 확인합니다.
- isRunningService-getForegroundApp에 대한 도우미 함수
이것은 모든 extend (:
private RunningAppProcessInfo getForegroundApp() {
RunningAppProcessInfo result=null, info=null;
if(mActivityManager==null)
mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List <RunningAppProcessInfo> l = mActivityManager.getRunningAppProcesses();
Iterator <RunningAppProcessInfo> i = l.iterator();
while(i.hasNext()){
info = i.next();
if(info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
&& !isRunningService(info.processName)){
result=info;
break;
}
}
return result;
}
private ComponentName getActivityForApp(RunningAppProcessInfo target){
ComponentName result=null;
ActivityManager.RunningTaskInfo info;
if(target==null)
return null;
if(mActivityManager==null)
mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List <ActivityManager.RunningTaskInfo> l = mActivityManager.getRunningTasks(9999);
Iterator <ActivityManager.RunningTaskInfo> i = l.iterator();
while(i.hasNext()){
info=i.next();
if(info.baseActivity.getPackageName().equals(target.processName)){
result=info.topActivity;
break;
}
}
return result;
}
private boolean isStillActive(RunningAppProcessInfo process, ComponentName activity)
{
// activity can be null in cases, where one app starts another. for example, astro
// starting rock player when a move file was clicked. we dont have an activity then,
// but the package exits as soon as back is hit. so we can ignore the activity
// in this case
if(process==null)
return false;
RunningAppProcessInfo currentFg=getForegroundApp();
ComponentName currentActivity=getActivityForApp(currentFg);
if(currentFg!=null && currentFg.processName.equals(process.processName) &&
(activity==null || currentActivity.compareTo(activity)==0))
return true;
Slog.i(TAG, "isStillActive returns false - CallerProcess: " + process.processName + " CurrentProcess: "
+ (currentFg==null ? "null" : currentFg.processName) + " CallerActivity:" + (activity==null ? "null" : activity.toString())
+ " CurrentActivity: " + (currentActivity==null ? "null" : currentActivity.toString()));
return false;
}
private boolean isRunningService(String processname){
if(processname==null || processname.isEmpty())
return false;
RunningServiceInfo service;
if(mActivityManager==null)
mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List <RunningServiceInfo> l = mActivityManager.getRunningServices(9999);
Iterator <RunningServiceInfo> i = l.iterator();
while(i.hasNext()){
service = i.next();
if(service.process.equals(processname))
return true;
}
return false;
}
답변
다음 코드를 시도하십시오.
ActivityManager activityManager = (ActivityManager) newContext.getSystemService( Context.ACTIVITY_SERVICE );
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for(RunningAppProcessInfo appProcess : appProcesses){
if(appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
Log.i("Foreground App", appProcess.processName);
}
}
프로세스 이름은 포 그라운드에서 실행중인 앱의 패키지 이름입니다. 애플리케이션의 패키지 이름과 비교하십시오. 동일하면 애플리케이션이 포 그라운드에서 실행 중입니다.
귀하의 질문에 대한 답변이 되었기를 바랍니다.
답변
롤리팝 이후로 이것은 바뀌 었습니다. 해당 사용자가 설정-> 보안-> (마지막으로 스크롤) 사용 권한이있는 앱-> 앱에 권한 부여하기 전에 아래 코드를 찾으십시오.
private void printForegroundTask() {
String currentApp = "NULL";
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
currentApp = tasks.get(0).processName;
}
Log.e(TAG, "Current App in foreground is: " + currentApp);
}
답변
자체 서비스 / 백그라운드 스레드에서 앱이 포 그라운드에 있는지 여부를 확인해야하는 경우. 이것이 내가 구현 한 방법이며 나를 위해 잘 작동합니다.
public class TestApplication extends Application implements Application.ActivityLifecycleCallbacks {
public static WeakReference<Activity> foregroundActivityRef = null;
@Override
public void onActivityStarted(Activity activity) {
foregroundActivityRef = new WeakReference<>(activity);
}
@Override
public void onActivityStopped(Activity activity) {
if (foregroundActivityRef != null && foregroundActivityRef.get() == activity) {
foregroundActivityRef = null;
}
}
// IMPLEMENT OTHER CALLBACK METHODS
}
이제 앱이 포 그라운드에 있는지 여부를 다른 클래스에서 확인하려면 다음을 호출하면됩니다.
if(TestApplication.foregroundActivityRef!=null){
// APP IS IN FOREGROUND!
// We can also get the activity that is currently visible!
}
업데이트 ( SHS가 지적한대로 ) :
Application 클래스의 onCreate
메서드 에서 콜백을 등록하는 것을 잊지 마십시오 .
@Override
public void onCreate() {
...
registerActivityLifecycleCallbacks(this);
}
답변
포 그라운드 애플리케이션을 결정하기 위해 포 그라운드 앱을 감지하는 데 사용할 수 있으며 https://github.com/ricvalerio/foregroundappchecker 를 사용할 수 있습니다 . 기기의 Android 버전에 따라 다른 방법을 사용합니다.
서비스의 경우 저장소는 필요한 코드도 제공합니다. 기본적으로 android studio가 서비스를 생성하도록 한 다음 onCreate가 appChecker를 사용하는 스 니펫을 추가합니다. 그러나 권한을 요청해야합니다.
답변
고려 getRunningTasks()
되지하고 getRunningAppProcesses()
신뢰할 수 없습니다, I에 유래에 언급 된 두 방법을 결합하는 결정을했다 :
private boolean isAppInForeground(Context context)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();
return foregroundTaskPackageName.toLowerCase().equals(context.getPackageName().toLowerCase());
}
else
{
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE)
{
return true;
}
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
// App is foreground, but screen is locked, so show notification
return km.inKeyguardRestrictedInputMode();
}
}