Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: get installed packages information #502

Merged
merged 16 commits into from Mar 9, 2023
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Expand Up @@ -14,6 +14,8 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />

<application android:allowBackup="true" tools:ignore="GoogleAppIndexingWarning">
<receiver android:name="io.appium.uiautomator2.server.ServerInstrumentation$PowerConnectionReceiver"
Expand Down
54 changes: 54 additions & 0 deletions app/src/main/java/io/appium/uiautomator2/handler/GetPackages.java
@@ -0,0 +1,54 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.appium.uiautomator2.handler;

import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static io.appium.uiautomator2.model.Session.NO_ID;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;

import java.util.ArrayList;
import java.util.List;

import io.appium.uiautomator2.handler.request.NoSessionCommandHandler;
import io.appium.uiautomator2.handler.request.SafeRequestHandler;
import io.appium.uiautomator2.http.AppiumResponse;
import io.appium.uiautomator2.http.IHttpRequest;
import io.appium.uiautomator2.model.api.touch.appium.PackageModel;

public class GetPackages extends SafeRequestHandler implements NoSessionCommandHandler {
public GetPackages(String mappedUri) {
mykola-mokhnach marked this conversation as resolved.
Show resolved Hide resolved
super(mappedUri);
}

@Override
protected AppiumResponse safeHandle(IHttpRequest request) {
List<PackageModel> appDetails = new ArrayList<PackageModel>();
mykola-mokhnach marked this conversation as resolved.
Show resolved Hide resolved
PackageManager manager = getApplicationContext().getPackageManager();
List<ApplicationInfo> apps = manager.getInstalledApplications(manager.GET_META_DATA);
for (ApplicationInfo appInfo : apps) {
// Filtering out unnecessary sub packages without Intent
if (manager.getLaunchIntentForPackage(appInfo.packageName) != null) {
appDetails.add(new PackageModel(appInfo.packageName,
manager.getLaunchIntentForPackage(appInfo.packageName).getComponent().getClassName(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happen when getLaunchIntentForPackage(appInfo.packageName) is null, or getComponent is null. They are nullable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They both are Nullable, if an application has an intent then for sure it will have a component, so application with no component will automatically get filter out from the 46 condition and also getComponent is also Nullable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, missed here called the method twice.
This endpoint tries to show installed packages and each information, then maybe if would be nice to keep the package name (since it exists) but no activities rather than filtering the package out entirely. What do you think?
So, the user can understand some packages exist in the device but they has no launchable activities by this endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intend was to show all the main applications since the package without Intent is just a subpackage of it's parent package which can just create confusion to the user and actually it's pretty much useless, if later on anyone needs that then surely we can modify accordingly but i feel it's unnecessary right now to show?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then, could you leave the intention as docstring in this class for future maintenance?
GetPackages made me think the app package is primary, then app activities etc as additional information. The current intention is to get app activities information than its package (since filter by package).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have already given a comment on that condition, You want me to create docstring with more info?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, could you leave what kind of activities will be available, and no activities packages won't be available?
I mean not a comment for the implementation, just this method's entire behavior as the module's description. Also, it wole be appreciate to add this method uses android.permission.QUERY_ALL_PACKAGES here, or a comment in the manifest to link each

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, missing commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done now

(String) manager.getApplicationLabel(appInfo)));
mykola-mokhnach marked this conversation as resolved.
Show resolved Hide resolved
}
}
return new AppiumResponse(NO_ID, appDetails);
}
}
@@ -0,0 +1,52 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.appium.uiautomator2.model.api.touch.appium;

import javax.annotation.Nullable;

public class PackageModel {
private final
mykola-mokhnach marked this conversation as resolved.
Show resolved Hide resolved
String packageName;
private final @Nullable
mykola-mokhnach marked this conversation as resolved.
Show resolved Hide resolved
String packageActivity;
private final
String appName;

public PackageModel(
String packageName,
String packageActivity,
String appName) {
this.packageName = packageName;
this.packageActivity = packageActivity;
this.appName = appName;
}

@Nullable
public String getPackageName() {
return packageName;
}

@Nullable
public String getPackageActivity() {
return packageActivity;
}

@Nullable
public String getAppName() {
return appName;
}
}
Expand Up @@ -48,6 +48,7 @@
import io.appium.uiautomator2.handler.GetElementScreenshot;
import io.appium.uiautomator2.handler.GetName;
import io.appium.uiautomator2.handler.GetOrientation;
import io.appium.uiautomator2.handler.GetPackages;
import io.appium.uiautomator2.handler.GetRect;
import io.appium.uiautomator2.handler.GetRotation;
import io.appium.uiautomator2.handler.GetSessionDetails;
Expand Down Expand Up @@ -161,6 +162,7 @@ private void registerPostHandler() {

private void registerGetHandler() {
register(getHandler, new Status("/status"));
register(getHandler,new GetPackages("/appium/device/apps"));
register(getHandler, new GetSessions("/sessions"));
register(getHandler, new GetSessionDetails("/session/:sessionId"));
register(getHandler, new CaptureScreenshot("/session/:sessionId/screenshot"));
Expand Down