Skip to content

Commit 87a02ec

Browse files
committed
feat: add intent-filters to activities, export activity-aliases
1 parent efe16af commit 87a02ec

File tree

6 files changed

+380
-27
lines changed

6 files changed

+380
-27
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ version.workspace = true
1212

1313
[dependencies]
1414
apk-info-axml.workspace = true
15+
apk-info-xml.workspace = true
1516
apk-info-zip.workspace = true
1617
serde.workspace = true
1718
serde_json.workspace = true

core/src/apk.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ use std::io::{self, BufReader, Read};
66
use std::path::Path;
77

88
use apk_info_axml::{ARSC, AXML};
9+
use apk_info_xml::Element;
910
use apk_info_zip::{FileCompressionType, Signature, ZipEntry, ZipError};
1011

1112
use crate::errors::APKError;
12-
use crate::models::{Activity, Attribution, Permission, Provider, Receiver, Service, XAPKManifest};
13+
use crate::models::{
14+
Activity, ActivityAlias, Attribution, IntentFilter, Permission, Provider, Receiver, Service,
15+
XAPKManifest,
16+
};
1317

1418
/// The name of the manifest to be searched for in the zip archive.
1519
const ANDROID_MANIFEST_PATH: &str = "AndroidManifest.xml";
@@ -598,12 +602,35 @@ impl Apk {
598602
self.axml.get_main_activities()
599603
}
600604

605+
#[inline]
606+
fn get_intent_filters<'a>(
607+
&'a self,
608+
element: &'a Element,
609+
) -> impl Iterator<Item = IntentFilter<'a>> {
610+
element
611+
.childrens()
612+
.filter(|intent| intent.name() == "intent-filter")
613+
.map(|intent| {
614+
let mut action = None;
615+
let mut category = None;
616+
617+
for child in intent.childrens() {
618+
match child.name() {
619+
"action" => action = child.attr("name"),
620+
"category" => category = child.attr("name"),
621+
_ => {}
622+
}
623+
}
624+
625+
IntentFilter { action, category }
626+
})
627+
}
628+
601629
/// Retrieves all `<activity>` components declared in the manifest.
602630
///
603631
/// See: <https://developer.android.com/guide/topics/manifest/activity-element>
604632
#[inline]
605633
pub fn get_activities(&self) -> impl Iterator<Item = Activity<'_>> {
606-
// iterates only on childrens, since this tag lives only as a child of the <manifest> tag
607634
self.axml
608635
.root
609636
.descendants()
@@ -617,6 +644,28 @@ impl Apk {
617644
parent_activity_name: el.attr("parent_activity_name"),
618645
permission: el.attr("permission"),
619646
process: el.attr("process"),
647+
intent_filters: self.get_intent_filters(el).collect(),
648+
})
649+
}
650+
651+
/// Retrieves all `<activity-alias>` components declared in the manifest.
652+
///
653+
/// See: <https://developer.android.com/guide/topics/manifest/activity-element>
654+
#[inline]
655+
pub fn get_activity_aliases(&self) -> impl Iterator<Item = ActivityAlias<'_>> {
656+
self.axml
657+
.root
658+
.descendants()
659+
.filter(|&el| el.name() == "activity-alias")
660+
.map(|el| ActivityAlias {
661+
enabled: el.attr("enabled"),
662+
exported: el.attr("exported"),
663+
icon: el.attr("icon"),
664+
label: el.attr("label"),
665+
name: el.attr("name"),
666+
permission: el.attr("permission"),
667+
target_activity: el.attr("targetActivity"),
668+
intent_filters: self.get_intent_filters(el).collect(),
620669
})
621670
}
622671

core/src/models.rs

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,20 @@ pub struct XAPKManifest {
99
pub package_name: String,
1010
}
1111

12-
/// Represents `<meta-data>` in manifest
12+
/// Represents `<intent-filter>` in manifest
1313
///
14-
/// See: <https://developer.android.com/guide/topics/manifest/meta-data-element>
14+
/// More information: <https://developer.android.com/guide/topics/manifest/intent-filter-element>
1515
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
16-
pub struct MetaData<'a> {
17-
/// A unique name for the item
16+
pub struct IntentFilter<'a> {
17+
/// The name of the action filter
1818
///
19-
/// See: <https://developer.android.com/guide/topics/manifest/meta-data-element#nm>
20-
pub name: Option<&'a str>,
21-
22-
/// A reference to a resource.
23-
///
24-
/// See: <https://developer.android.com/guide/topics/manifest/meta-data-element#rsrc>
25-
pub resource: Option<&'a str>,
19+
/// See: <https://developer.android.com/guide/topics/manifest/action-element>
20+
pub action: Option<&'a str>,
2621

27-
/// The value assigned to the item.
22+
/// The name of category filter
2823
///
29-
/// See: <https://developer.android.com/guide/topics/manifest/meta-data-element#val>
30-
pub value: Option<&'a str>,
24+
/// See: <https://developer.android.com/guide/topics/manifest/category-element>
25+
pub category: Option<&'a str>,
3126
}
3227

3328
/// Represents `<activity>` in manifest
@@ -74,6 +69,57 @@ pub struct Activity<'a> {
7469
///
7570
/// See: <https://developer.android.com/guide/topics/manifest/activity-element#proc>
7671
pub process: Option<&'a str>,
72+
73+
/// A list of all declared `<intent-filter>` for a given activity
74+
///
75+
/// See: <https://developer.android.com/guide/topics/manifest/intent-filter-element>
76+
pub intent_filters: Vec<IntentFilter<'a>>,
77+
}
78+
79+
/// Represents `<activity-alias>` in manifest
80+
///
81+
/// More information: <https://developer.android.com/guide/topics/manifest/activity-alias-element>
82+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
83+
pub struct ActivityAlias<'a> {
84+
/// Whether the target activity can be instantiated by the system through this alias.
85+
///
86+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#enabled>
87+
pub enabled: Option<&'a str>,
88+
89+
/// Whether the components of other applications can launch the target activity through this alias.
90+
///
91+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#exported>
92+
pub exported: Option<&'a str>,
93+
94+
/// An icon for the target activity when presented to users through the alias.
95+
///
96+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#icon>
97+
pub icon: Option<&'a str>,
98+
99+
/// A user-readable label for the alias when presented to users through the alias.
100+
///
101+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#label>
102+
pub label: Option<&'a str>,
103+
104+
/// A unique name for the alias.
105+
///
106+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#nm>
107+
pub name: Option<&'a str>,
108+
109+
/// The name of a permission that clients must have to launch the target activity or get it to do something using the alias.
110+
///
111+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#prmsn>
112+
pub permission: Option<&'a str>,
113+
114+
/// The name of the activity that can be activated through the alias.
115+
///
116+
/// See: <https://developer.android.com/guide/topics/manifest/activity-alias-element#trgt>
117+
pub target_activity: Option<&'a str>,
118+
119+
/// A list of all declared `<intent-filter>` for a given activity
120+
///
121+
/// See: <https://developer.android.com/guide/topics/manifest/intent-filter-element>
122+
pub intent_filters: Vec<IntentFilter<'a>>,
77123
}
78124

79125
/// Represents `<permission>` in manifest

python/apk_info.pyi

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,19 @@ class APK:
783783
"""
784784
...
785785

786+
def get_activity_aliases(self) -> list[ActivityAlias]:
787+
"""
788+
Retrieves all `<activity-alias>` components declared in the manifest.
789+
790+
See: <a href="https://developer.android.com/guide/topics/manifest/activity-alias-element" target="_blank">https://developer.android.com/guide/topics/manifest/activity-alias-element</a>
791+
792+
Returns
793+
-------
794+
list[ActivityAlias]
795+
A list of found aliases
796+
"""
797+
...
798+
786799
def get_services(self) -> list[Service]:
787800
"""
788801
Retrieves all `<service>` components declared in the manifest.
@@ -1020,6 +1033,29 @@ type SignatureType = (
10201033
Represents all available signatures
10211034
"""
10221035

1036+
@dataclass(frozen=True)
1037+
class IntentFilter:
1038+
"""
1039+
Represents `<intent-filter>` in manifest
1040+
1041+
More information:
1042+
<a href="https://developer.android.com/guide/topics/manifest/intent-filter-element" target="_blank">https://developer.android.com/guide/topics/manifest/intent-filter-element</a>
1043+
"""
1044+
1045+
action: str | None
1046+
"""
1047+
The name of the action filter
1048+
1049+
See: https://developer.android.com/guide/topics/manifest/action-element
1050+
"""
1051+
1052+
category: str | None
1053+
"""
1054+
The name of category filter
1055+
1056+
See: https://developer.android.com/guide/topics/manifest/category-element
1057+
"""
1058+
10231059
@dataclass(frozen=True)
10241060
class Activity:
10251061
"""
@@ -1086,6 +1122,78 @@ class Activity:
10861122
See: https://developer.android.com/guide/topics/manifest/activity-element#proc
10871123
"""
10881124

1125+
intent_filters: list[IntentFilter]
1126+
"""
1127+
A list of all declared `<intent-filter>` for a given activity
1128+
1129+
See: https://developer.android.com/guide/topics/manifest/intent-filter-element
1130+
"""
1131+
1132+
@dataclass(frozen=True)
1133+
class ActivityAlias:
1134+
"""
1135+
Represents `<activity-alias>` in manifest
1136+
1137+
More information:
1138+
<a href="https://developer.android.com/guide/topics/manifest/activity-alias-element">https://developer.android.com/guide/topics/manifest/activity-alias-element</a>
1139+
"""
1140+
1141+
enabled: str | None
1142+
"""
1143+
Whether the target activity can be instantiated by the system through this alias.
1144+
1145+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#enabled
1146+
"""
1147+
1148+
exported: str | None
1149+
"""
1150+
Whether the components of other applications can launch the target activity through this alias.
1151+
1152+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#exported
1153+
"""
1154+
1155+
icon: str | None
1156+
"""
1157+
An icon for the target activity when presented to users through the alias.
1158+
1159+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#icon
1160+
"""
1161+
1162+
label: str | None
1163+
"""
1164+
A user-readable label for the alias when presented to users through the alias.
1165+
1166+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#label
1167+
"""
1168+
1169+
name: str | None
1170+
"""
1171+
A unique name for the alias.
1172+
1173+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#nm
1174+
"""
1175+
1176+
permission: str | None
1177+
"""
1178+
The name of a permission that clients must have to launch the target activity or get it to do something using the alias.
1179+
1180+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#prmsn
1181+
"""
1182+
1183+
target_activity: str | None
1184+
"""
1185+
The name of the activity that can be activated through the alias.
1186+
1187+
See: https://developer.android.com/guide/topics/manifest/activity-alias-element#trgt
1188+
"""
1189+
1190+
intent_filters: list[IntentFilter]
1191+
"""
1192+
A list of all declared `<intent-filter>` for a given activity
1193+
1194+
See: https://developer.android.com/guide/topics/manifest/intent-filter-element
1195+
"""
1196+
10891197
@dataclass(frozen=True)
10901198
class Permission:
10911199
"""

0 commit comments

Comments
 (0)