Finnes det en egen Android-måte for å hente en referanse til aktiviteten som kjører for øyeblikket, fra en tjeneste?
Jeg har en tjeneste som kjører i bakgrunnen, og jeg vil gjerne oppdatere min nåværende aktivitet når en hendelse inntreffer (i tjenesten). Finnes det en enkel måte å gjøre det på (som den jeg foreslo ovenfor)?
Her er en god måte å gjøre det på ved hjelp av aktivitetsadministratoren. Du henter i utgangspunktet runningTasks fra aktivitetsbehandleren. Den returnerer alltid den aktive oppgaven først. Derfra kan du hente topActivity.
Det finnes en enkel måte å få en liste over oppgaver som kjører fra ActivityManager-tjenesten. Du kan be om et maksimalt antall oppgaver som kjører på telefonen, og som standard returneres den aktive oppgaven først.
Når du har det, kan du hente et ComponentName-objekt ved å be om topActivity fra listen.
Her er et eksempel.
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
Log.d("topActivity", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClassName());
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
Du trenger følgende tillatelse i manifestet ditt:
<uses-permission android:name="android.permission.GET_TASKS"/>
Google har truet med å fjerne apper fra Play Store hvis de bruker tilgjengelighetstjenester til andre formål enn tilgjengelighet. Men dette skal etter sigende være under revurdering.
Tilgjengelighetstjeneste
AccessibilityService
.onAccessibilityEvent
ser du etter `TYPE_WINDOW_STATE_CHANGED
hendelsestype for å avgjøre når det aktuelle vinduet endres.PackageManager.getActivityInfo()
.GET_TASKS
-tillatelsen.AccessibilityService
, kan vedkommende ikke trykke på OK-knappen hvis en app har lagt et overlegg på skjermen. Noen apper som gjør dette, er Velis Auto Brightness og Lux. Dette kan være forvirrende fordi brukeren kanskje ikke vet hvorfor de ikke kan trykke på knappen eller hvordan de kan omgå det.AccessibilityService
vet ikke hva som er gjeldende aktivitet før den første endringen av aktivitet.public class WindowChangeDetectingService extends AccessibilityService {
@Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
if (event.getPackageName() != null && event.getClassName() != null) {
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
ActivityInfo activityInfo = tryGetActivity(componentName);
boolean isActivity = activityInfo != null;
if (isActivity)
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {}
}
Flett dette inn i manifestet:
<application>
<service
android:label="@string/accessibility_service_name"
android:name=".WindowChangeDetectingService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibilityservice"/>
</service>
</application>
Legg dette inn i res/xml/accessibilityservice.xml
:
<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
start in Android 4.1.1 -->
<accessibility-service
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews"
android:description="@string/accessibility_service_description"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="UnusedAttribute"/>
Hver bruker av appen må eksplisitt aktivere AccessibilityService
for at den skal kunne brukes. Se dette StackOverflow-svaret for hvordan du gjør dette.
Vær oppmerksom på at brukeren ikke kan trykke på OK-knappen når han/hun prøver å aktivere tilgjengelighetstjenesten hvis en app har lagt et overlegg på skjermen, for eksempel Velis Auto Brightness eller Lux.
Finnes det en egen Android-måte for å få en referanse til aktiviteten som kjører for øyeblikket fra en tjeneste?
Det er ikke sikkert at du eier den aktuelle aktiviteten.
Jeg har en tjeneste som kjører i bakgrunnen, og jeg vil gjerne oppdatere min nåværende aktivitet når en hendelse inntreffer (i tjenesten). Finnes det en enkel måte å gjøre det på (som den jeg foreslo ovenfor)?
Intent
til aktiviteten -- her er et eksempelprosjekt som viser dette mønsteretPendingIntent
(f.eks. via createPendingResult()
) som tjenesten påkaller.bindService()
, og få tjenesten til å kalle en hendelsesmetode på tilbakeringings-/lytterobjektet.Intent
til aktiviteten, med en lavprioritert BroadcastReceiver
som backup (for å utløse en Notification
hvis aktiviteten ikke er på skjermen) -- her er et blogginnlegg med mer om dette mønsteret.