如何访问第三方 sdk 的 activity 名称
How to get access to third party sdk's activity names
我需要知道屏幕何时在应用程序中可见,我如何才能知道哪个 activity 与该屏幕相关。特别是如果我使用另一个 SDK 来获取登录屏幕。所以我需要知道这些屏幕的 activity 名称和包名称。
目前,我的 BaseActivity
class 中有一个方法可以在屏幕之间导航时记录 activity 名称。但是当我点击登录按钮时,它会打开另一个属于第三方 SDK 的屏幕。
/**
* Logs the component with activity name and method
*
* @param tag
*/
private void logActivityInfo(String tag) {
mLogService.logScreenInfo(this.getClass().getSimpleName() + tag);
}
我认为如果我在看到该屏幕时有一个获取 activity 名称的技巧,就可以解决这个问题。因为 Android Profiler
在所有屏幕之间移动时显示所有 activity 名称。如果有人可以帮助我找到解决这个问题的方法,那就太好了。
您可以使用 Android 中的辅助功能服务来执行此操作。我有一个适合我的代码。你可以试试
package com.butterfly.instaliker;
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)
if(componentName.flattenToShortString().equalsIgnoreCase(" com.instagram.android/com.instagram.mainactivity.MainActivity")){
scrollAndLike(event);
}
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
}
private void scrollAndLike(AccessibilityEvent event) {
AccessibilityNodeInfo nodeInfo = event.getSource();
Log.i("jude", "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo);
if (nodeInfo == null) {
return;
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {}
}
您的应用应该具有您需要用户启用的辅助功能权限,例如
if (!isAccessibilitySettingsOn(getApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent,1000);
}
else{
startService(new Intent(this,WindowChangeDetectingService.class));
}
和
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1000){
startService(new Intent(this,WindowChangeDetectingService.class));
}
}
private boolean isAccessibilitySettingsOn(Context mContext) {
String TAG = "jude";
int accessibilityEnabled = 0;
final String service = getPackageName() + "/" + WindowChangeDetectingService.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
mContext.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
} catch (Settings.SettingNotFoundException e) {
Log.e(TAG, "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == 1) {
Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
String settingValue = Settings.Secure.getString(
mContext.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
if (accessibilityService.equalsIgnoreCase(service)) {
Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
return true;
}
}
}
} else {
Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
}
return false;
}
来源:
也许跟踪 activity 生命周期事件可以解决您的问题这里是一些示例代码。
public class MyApplication extends Application
implements Application.ActivityLifecycleCallbacks {
private int numStarted;
...
@Override
public void onCreate() {
...
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityStarted(Activity activity) {
//some code
}
@Override
public void onActivityStopped(Activity activity) {
//some code
}
}
因为它们会 运行 在您的应用程序上下文中,所以在那里跟踪它们也应该列出它们。
我需要知道屏幕何时在应用程序中可见,我如何才能知道哪个 activity 与该屏幕相关。特别是如果我使用另一个 SDK 来获取登录屏幕。所以我需要知道这些屏幕的 activity 名称和包名称。
目前,我的 BaseActivity
class 中有一个方法可以在屏幕之间导航时记录 activity 名称。但是当我点击登录按钮时,它会打开另一个属于第三方 SDK 的屏幕。
/**
* Logs the component with activity name and method
*
* @param tag
*/
private void logActivityInfo(String tag) {
mLogService.logScreenInfo(this.getClass().getSimpleName() + tag);
}
我认为如果我在看到该屏幕时有一个获取 activity 名称的技巧,就可以解决这个问题。因为 Android Profiler
在所有屏幕之间移动时显示所有 activity 名称。如果有人可以帮助我找到解决这个问题的方法,那就太好了。
您可以使用 Android 中的辅助功能服务来执行此操作。我有一个适合我的代码。你可以试试
package com.butterfly.instaliker;
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)
if(componentName.flattenToShortString().equalsIgnoreCase(" com.instagram.android/com.instagram.mainactivity.MainActivity")){
scrollAndLike(event);
}
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
}
private void scrollAndLike(AccessibilityEvent event) {
AccessibilityNodeInfo nodeInfo = event.getSource();
Log.i("jude", "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo);
if (nodeInfo == null) {
return;
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {}
}
您的应用应该具有您需要用户启用的辅助功能权限,例如
if (!isAccessibilitySettingsOn(getApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent,1000);
}
else{
startService(new Intent(this,WindowChangeDetectingService.class));
}
和
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1000){
startService(new Intent(this,WindowChangeDetectingService.class));
}
}
private boolean isAccessibilitySettingsOn(Context mContext) {
String TAG = "jude";
int accessibilityEnabled = 0;
final String service = getPackageName() + "/" + WindowChangeDetectingService.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
mContext.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
} catch (Settings.SettingNotFoundException e) {
Log.e(TAG, "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == 1) {
Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
String settingValue = Settings.Secure.getString(
mContext.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
if (accessibilityService.equalsIgnoreCase(service)) {
Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
return true;
}
}
}
} else {
Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
}
return false;
}
来源:
也许跟踪 activity 生命周期事件可以解决您的问题这里是一些示例代码。
public class MyApplication extends Application
implements Application.ActivityLifecycleCallbacks {
private int numStarted;
...
@Override
public void onCreate() {
...
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityStarted(Activity activity) {
//some code
}
@Override
public void onActivityStopped(Activity activity) {
//some code
}
}
因为它们会 运行 在您的应用程序上下文中,所以在那里跟踪它们也应该列出它们。