Skip to content

Commit 389c2ed

Browse files
committed
Handle errors
1 parent 0c60b27 commit 389c2ed

File tree

3 files changed

+96
-78
lines changed

3 files changed

+96
-78
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ fn android_main(_android_app: AndroidApp) {
1313
Intent::new(env, Action::Send)
1414
.with_type("text/plain")
1515
.with_extra(Extra::Text, "Hello World!")
16-
.create_chooser()
16+
.into_chooser()
1717
.start_activity()
18+
.unwrap()
1819
});
19-
20-
loop {}
2120
}
2221
```

example/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ fn android_main(_android_app: AndroidApp) {
77
Intent::new(env, Action::Send)
88
.with_type("text/plain")
99
.with_extra(Extra::Text, "Hello World!")
10-
.create_chooser()
10+
.into_chooser()
1111
.start_activity()
12+
.unwrap()
1213
});
1314

1415
loop {}

src/intent.rs

Lines changed: 92 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,74 @@
11
use jni::{
2+
errors::Error,
23
objects::{JObject, JString},
34
JNIEnv,
45
};
56

7+
struct Inner<'env> {
8+
env: JNIEnv<'env>,
9+
object: JObject<'env>,
10+
}
11+
612
/// A messaging object you can use to request an action from another android app component.
713
#[must_use]
814
pub struct Intent<'env> {
9-
pub env: JNIEnv<'env>,
10-
pub object: JObject<'env>,
15+
inner: Result<Inner<'env>, Error>,
1116
}
1217

1318
impl<'env> Intent<'env> {
1419
pub fn from_object(env: JNIEnv<'env>, object: JObject<'env>) -> Self {
15-
Self { env, object }
20+
Self {
21+
inner: Ok(Inner { env, object }),
22+
}
1623
}
1724

18-
pub fn new(env: JNIEnv<'env>, action: impl AsRef<str>) -> Self {
19-
let intent_class = env.find_class("android/content/Intent").unwrap();
20-
let action_view = env
21-
.get_static_field(intent_class, action.as_ref(), "Ljava/lang/String;")
22-
.unwrap();
23-
24-
let intent = env
25-
.new_object(intent_class, "(Ljava/lang/String;)V", &[action_view.into()])
26-
.unwrap();
25+
fn from_fn(f: impl FnOnce() -> Result<Inner<'env>, Error>) -> Self {
26+
let inner = f();
27+
Self { inner }
28+
}
2729

28-
Self::from_object(env, intent)
30+
pub fn new(env: JNIEnv<'env>, action: impl AsRef<str>) -> Self {
31+
Self::from_fn(|| {
32+
let intent_class = env.find_class("android/content/Intent")?;
33+
let action_view =
34+
env.get_static_field(intent_class, action.as_ref(), "Ljava/lang/String;")?;
35+
36+
let intent =
37+
env.new_object(intent_class, "(Ljava/lang/String;)V", &[action_view.into()])?;
38+
39+
Ok(Inner {
40+
env,
41+
object: intent,
42+
})
43+
})
2944
}
3045

3146
pub fn new_with_uri(env: JNIEnv<'env>, action: impl AsRef<str>, uri: impl AsRef<str>) -> Self {
32-
let url_string = env.new_string(uri).unwrap();
33-
let uri_class = env.find_class("android/net/Uri").unwrap();
34-
let uri = env
35-
.call_static_method(
47+
Self::from_fn(|| {
48+
let url_string = env.new_string(uri)?;
49+
let uri_class = env.find_class("android/net/Uri")?;
50+
let uri = env.call_static_method(
3651
uri_class,
3752
"parse",
3853
"(Ljava/lang/String;)Landroid/net/Uri;",
3954
&[JString::from(url_string).into()],
40-
)
41-
.unwrap();
55+
)?;
4256

43-
let intent_class = env.find_class("android/content/Intent").unwrap();
44-
let action_view = env
45-
.get_static_field(intent_class, action.as_ref(), "Ljava/lang/String;")
46-
.unwrap();
57+
let intent_class = env.find_class("android/content/Intent")?;
58+
let action_view =
59+
env.get_static_field(intent_class, action.as_ref(), "Ljava/lang/String;")?;
4760

48-
let intent = env
49-
.new_object(
61+
let intent = env.new_object(
5062
intent_class,
5163
"(Ljava/lang/String;Landroid/net/Uri;)V",
5264
&[action_view.into(), uri.into()],
53-
)
54-
.unwrap();
65+
)?;
5566

56-
Self::from_object(env, intent)
67+
Ok(Inner {
68+
env,
69+
object: intent,
70+
})
71+
})
5772
}
5873

5974
/// Add extended data to the intent.
@@ -65,55 +80,54 @@ impl<'env> Intent<'env> {
6580
/// intent.push_extra(Extra::Text, "Hello World!")
6681
/// # })
6782
/// ```
68-
pub fn push_extra(&self, key: impl AsRef<str>, value: impl AsRef<str>) {
69-
let key = self.env.new_string(key).unwrap();
70-
let value = self.env.new_string(value).unwrap();
83+
pub fn with_extra(self, key: impl AsRef<str>, value: impl AsRef<str>) -> Self {
84+
self.and_then(|inner| {
85+
let key = inner.env.new_string(key)?;
86+
let value = inner.env.new_string(value)?;
7187

72-
self.env
73-
.call_method(
74-
self.object,
88+
inner.env.call_method(
89+
inner.object,
7590
"putExtra",
7691
"(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;",
7792
&[key.into(), value.into()],
78-
)
79-
.unwrap();
80-
}
93+
)?;
8194

82-
pub fn with_extra(&self, key: impl AsRef<str>, value: impl AsRef<str>) -> &Self {
83-
self.push_extra(key, value);
84-
self
95+
Ok(inner)
96+
})
8597
}
8698

8799
/// Builds a new [`Action::Chooser`](Action) Intent that wraps the given target intent.
88100
/// ```no_run
89101
/// use android_intent::{Action, Intent};
90102
///
91103
/// # android_intent::with_current_env(|env| {
92-
/// let intent = Intent::new(env, Action::Send);
93-
/// let chooser_intent = intent.create_chooser();
104+
/// let intent = Intent::new(env, Action::Send).into_chhoser();
94105
/// # })
95106
/// ```
96-
pub fn create_chooser(&self) -> Self {
97-
self.create_chooser_with_title(None::<&str>)
107+
pub fn into_chooser(self) -> Self {
108+
self.into_chooser_with_title(None::<&str>)
98109
}
99110

100-
pub fn create_chooser_with_title(&self, title: Option<impl AsRef<str>>) -> Self {
101-
let title_value = title
102-
.map(|s| self.env.new_string(s).unwrap().into())
103-
.unwrap_or_else(|| JObject::null().into());
104-
105-
let intent_class = self.env.find_class("android/content/Intent").unwrap();
106-
let intent = self
107-
.env
108-
.call_static_method(
111+
pub fn into_chooser_with_title(self, title: Option<impl AsRef<str>>) -> Self {
112+
self.and_then(|mut inner| {
113+
let title_value = if let Some(title) = title {
114+
let s = inner.env.new_string(title)?;
115+
s.into()
116+
} else {
117+
JObject::null().into()
118+
};
119+
120+
let intent_class = inner.env.find_class("android/content/Intent")?;
121+
let intent = inner.env.call_static_method(
109122
intent_class,
110123
"createChooser",
111124
"(Landroid/content/Intent;Ljava/lang/CharSequence;)Landroid/content/Intent;",
112-
&[self.object.into(), title_value],
113-
)
114-
.unwrap();
125+
&[inner.object.into(), title_value],
126+
)?;
115127

116-
Self::from_object(self.env, intent.try_into().unwrap())
128+
inner.object = intent.try_into()?;
129+
Ok(inner)
130+
})
117131
}
118132

119133
/// Set an explicit MIME data type.
@@ -125,35 +139,39 @@ impl<'env> Intent<'env> {
125139
/// intent.set_type("text/plain");
126140
/// # })
127141
/// ```
128-
pub fn set_type(&self, type_name: impl AsRef<str>) {
129-
let jstring = self.env.new_string(type_name).unwrap();
142+
pub fn with_type(self, type_name: impl AsRef<str>) -> Self {
143+
self.and_then(|inner| {
144+
let jstring = inner.env.new_string(type_name)?;
130145

131-
self.env
132-
.call_method(
133-
self.object,
146+
inner.env.call_method(
147+
inner.object,
134148
"setType",
135149
"(Ljava/lang/String;)Landroid/content/Intent;",
136150
&[jstring.into()],
137-
)
138-
.unwrap();
139-
}
151+
)?;
140152

141-
pub fn with_type(&self, type_name: impl AsRef<str>) -> &Self {
142-
self.set_type(type_name);
143-
self
153+
Ok(inner)
154+
})
144155
}
145156

146-
pub fn start_activity(&self) {
157+
pub fn start_activity(self) -> Result<(), Error> {
147158
let cx = ndk_context::android_context();
148159
let activity = unsafe { JObject::from_raw(cx.context() as jni::sys::jobject) };
149160

150-
self.env
151-
.call_method(
161+
self.inner.and_then(|inner| {
162+
inner.env.call_method(
152163
activity,
153164
"startActivity",
154165
"(Landroid/content/Intent;)V",
155-
&[self.object.into()],
156-
)
157-
.unwrap();
166+
&[inner.object.into()],
167+
)?;
168+
169+
Ok(())
170+
})
171+
}
172+
173+
fn and_then(mut self, f: impl FnOnce(Inner) -> Result<Inner, Error>) -> Self {
174+
self.inner = self.inner.and_then(f);
175+
self
158176
}
159177
}

0 commit comments

Comments
 (0)