1
1
use jni:: {
2
+ errors:: Error ,
2
3
objects:: { JObject , JString } ,
3
4
JNIEnv ,
4
5
} ;
5
6
7
+ struct Inner < ' env > {
8
+ env : JNIEnv < ' env > ,
9
+ object : JObject < ' env > ,
10
+ }
11
+
6
12
/// A messaging object you can use to request an action from another android app component.
7
13
#[ must_use]
8
14
pub struct Intent < ' env > {
9
- pub env : JNIEnv < ' env > ,
10
- pub object : JObject < ' env > ,
15
+ inner : Result < Inner < ' env > , Error > ,
11
16
}
12
17
13
18
impl < ' env > Intent < ' env > {
14
19
pub fn from_object ( env : JNIEnv < ' env > , object : JObject < ' env > ) -> Self {
15
- Self { env, object }
20
+ Self {
21
+ inner : Ok ( Inner { env, object } ) ,
22
+ }
16
23
}
17
24
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
+ }
27
29
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
+ } )
29
44
}
30
45
31
46
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 (
36
51
uri_class,
37
52
"parse" ,
38
53
"(Ljava/lang/String;)Landroid/net/Uri;" ,
39
54
& [ JString :: from ( url_string) . into ( ) ] ,
40
- )
41
- . unwrap ( ) ;
55
+ ) ?;
42
56
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;" ) ?;
47
60
48
- let intent = env
49
- . new_object (
61
+ let intent = env. new_object (
50
62
intent_class,
51
63
"(Ljava/lang/String;Landroid/net/Uri;)V" ,
52
64
& [ action_view. into ( ) , uri. into ( ) ] ,
53
- )
54
- . unwrap ( ) ;
65
+ ) ?;
55
66
56
- Self :: from_object ( env, intent)
67
+ Ok ( Inner {
68
+ env,
69
+ object : intent,
70
+ } )
71
+ } )
57
72
}
58
73
59
74
/// Add extended data to the intent.
@@ -65,55 +80,54 @@ impl<'env> Intent<'env> {
65
80
/// intent.push_extra(Extra::Text, "Hello World!")
66
81
/// # })
67
82
/// ```
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) ?;
71
87
72
- self . env
73
- . call_method (
74
- self . object ,
88
+ inner. env . call_method (
89
+ inner. object ,
75
90
"putExtra" ,
76
91
"(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;" ,
77
92
& [ key. into ( ) , value. into ( ) ] ,
78
- )
79
- . unwrap ( ) ;
80
- }
93
+ ) ?;
81
94
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
+ } )
85
97
}
86
98
87
99
/// Builds a new [`Action::Chooser`](Action) Intent that wraps the given target intent.
88
100
/// ```no_run
89
101
/// use android_intent::{Action, Intent};
90
102
///
91
103
/// # 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();
94
105
/// # })
95
106
/// ```
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 > )
98
109
}
99
110
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 (
109
122
intent_class,
110
123
"createChooser" ,
111
124
"(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
+ ) ?;
115
127
116
- Self :: from_object ( self . env , intent. try_into ( ) . unwrap ( ) )
128
+ inner. object = intent. try_into ( ) ?;
129
+ Ok ( inner)
130
+ } )
117
131
}
118
132
119
133
/// Set an explicit MIME data type.
@@ -125,35 +139,39 @@ impl<'env> Intent<'env> {
125
139
/// intent.set_type("text/plain");
126
140
/// # })
127
141
/// ```
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) ?;
130
145
131
- self . env
132
- . call_method (
133
- self . object ,
146
+ inner. env . call_method (
147
+ inner. object ,
134
148
"setType" ,
135
149
"(Ljava/lang/String;)Landroid/content/Intent;" ,
136
150
& [ jstring. into ( ) ] ,
137
- )
138
- . unwrap ( ) ;
139
- }
151
+ ) ?;
140
152
141
- pub fn with_type ( & self , type_name : impl AsRef < str > ) -> & Self {
142
- self . set_type ( type_name) ;
143
- self
153
+ Ok ( inner)
154
+ } )
144
155
}
145
156
146
- pub fn start_activity ( & self ) {
157
+ pub fn start_activity ( self ) -> Result < ( ) , Error > {
147
158
let cx = ndk_context:: android_context ( ) ;
148
159
let activity = unsafe { JObject :: from_raw ( cx. context ( ) as jni:: sys:: jobject ) } ;
149
160
150
- self . env
151
- . call_method (
161
+ self . inner . and_then ( |inner| {
162
+ inner . env . call_method (
152
163
activity,
153
164
"startActivity" ,
154
165
"(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
158
176
}
159
177
}
0 commit comments