11use 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]
814pub struct Intent < ' env > {
9- pub env : JNIEnv < ' env > ,
10- pub object : JObject < ' env > ,
15+ inner : Result < Inner < ' env > , Error > ,
1116}
1217
1318impl < ' 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