Facebook.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #include "../Platforms/iOS/iOS.h"
  4. namespace EE{
  5. /******************************************************************************/
  6. Facebook FB;
  7. #if IOS
  8. enum GET_FLAG
  9. {
  10. GET_ME =1<<0,
  11. GET_FRIENDS=1<<1,
  12. };
  13. static Byte Get;
  14. static void GetMe()
  15. {
  16. #if 0 // this doesn't support email
  17. [FBSDKProfile loadCurrentProfileWithCompletion:^(FBSDKProfile *profile, NSError *error)
  18. {
  19. if(profile)
  20. {
  21. FB._me.id =[profile.userID longLongValue];
  22. FB._me.name= profile.name;
  23. }
  24. }];
  25. #else
  26. if(FBSDKGraphRequest *graph_req=[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields":@"id,name,email"}])
  27. {
  28. [graph_req startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error)
  29. {
  30. if(NSDictionary *dict=result)
  31. {
  32. // this is called on the main thread, so no need for 'SyncLock'
  33. if(NSString *s=[dict objectForKey:@"id" ])FB._me.id =[s longLongValue];
  34. if(NSString *s=[dict objectForKey:@"name" ])FB._me.name =s;
  35. if(NSString *s=[dict objectForKey:@"email"])FB._me.email=s;
  36. }
  37. }];
  38. [graph_req release];
  39. }
  40. #endif
  41. }
  42. static void GetFriends()
  43. {
  44. if(FBSDKGraphRequest *graph_req=[[FBSDKGraphRequest alloc] initWithGraphPath:@"me/friends" parameters:@{@"fields":@"id,name"} HTTPMethod:@"GET"])
  45. {
  46. [graph_req startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error)
  47. {
  48. if(NSArray *friends=[result objectForKey:@"data"])
  49. {
  50. // this is called on the main thread, so no need for 'SyncLock'
  51. FB._friends.setNum([friends count]); REPA(FB._friends) // go from the end as we may remove users below
  52. {
  53. if(NSDictionary *dict=[friends objectAtIndex:i])
  54. {
  55. Facebook::User &user=FB._friends[i];
  56. if(NSString *s=[dict objectForKey:@"id" ])user.id =[s longLongValue];else user.id=0;
  57. if(NSString *s=[dict objectForKey:@"name"])user.name= s ;else user.name.clear();
  58. }else FB._friends.remove(i, true);
  59. }
  60. }
  61. }];
  62. [graph_req release];
  63. }
  64. }
  65. static void FBUpdate()
  66. {
  67. if(FB.loggedIn())
  68. {
  69. if(Get&GET_ME ){FlagDisable(Get, GET_ME ); GetMe ();}
  70. if(Get&GET_FRIENDS){FlagDisable(Get, GET_FRIENDS); GetFriends();}
  71. }
  72. }
  73. #endif
  74. /******************************************************************************/
  75. Facebook::Facebook()
  76. {
  77. #if 0 // there's only one 'Facebook' global 'FB' and it doesn't need clearing members to zero
  78. _me.clear();
  79. #endif
  80. }
  81. Bool Facebook::loggedIn()C
  82. {
  83. #if ANDROID
  84. JNI jni;
  85. if(jni && ActivityClass)
  86. if(JMethodID facebookLoggedIn=jni->GetStaticMethodID(ActivityClass, "facebookLoggedIn", "()Z"))
  87. return jni->CallStaticBooleanMethod(ActivityClass, facebookLoggedIn);
  88. #elif IOS
  89. return [FBSDKAccessToken currentAccessToken]!=null;
  90. #endif
  91. return false;
  92. }
  93. Facebook& Facebook::logIn()
  94. {
  95. #if ANDROID
  96. JNI jni;
  97. if(jni && ActivityClass && Activity)
  98. if(JMethodID facebookLogIn=jni->GetMethodID(ActivityClass, "facebookLogIn", "()V"))
  99. jni->CallVoidMethod(Activity, facebookLogIn);
  100. #elif IOS
  101. if(FBSDKLoginManager *login=[[FBSDKLoginManager alloc] init])
  102. {
  103. [login logInWithReadPermissions: @[@"public_profile", @"email", @"user_friends"] fromViewController:ViewController handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
  104. {
  105. if(error)
  106. {
  107. // error
  108. }else
  109. if(result && result.isCancelled)
  110. {
  111. // cancelled
  112. }else
  113. {
  114. // logged in
  115. FBUpdate();
  116. }
  117. }];
  118. [login release];
  119. }
  120. #endif
  121. return T;
  122. }
  123. Facebook& Facebook::logOut()
  124. {
  125. #if ANDROID
  126. JNI jni;
  127. if(jni && ActivityClass)
  128. if(JMethodID facebookLogOut=jni->GetStaticMethodID(ActivityClass, "facebookLogOut", "()V"))
  129. jni->CallStaticVoidMethod(ActivityClass, facebookLogOut);
  130. #elif IOS
  131. #if 0
  132. if(FBSDKLoginManager *login=[[FBSDKLoginManager alloc] init])
  133. {
  134. [login logOut ];
  135. [login release];
  136. }
  137. #else
  138. [FBSDKAccessToken setCurrentAccessToken:nil];
  139. [FBSDKProfile setCurrentProfile :nil];
  140. #endif
  141. #endif
  142. _me .clear();
  143. _friends.clear();
  144. return T;
  145. }
  146. Facebook& Facebook::getMe()
  147. {
  148. #if ANDROID
  149. JNI jni;
  150. if(jni && ActivityClass && Activity)
  151. if(JMethodID facebookGetMe=jni->GetMethodID(ActivityClass, "facebookGetMe", "()V"))
  152. jni->CallVoidMethod(Activity, facebookGetMe);
  153. #elif IOS
  154. if(loggedIn())GetMe();else{FlagEnable(Get, GET_ME); logIn();}
  155. #endif
  156. return T;
  157. }
  158. Facebook& Facebook::getFriends()
  159. {
  160. #if ANDROID
  161. JNI jni;
  162. if(jni && ActivityClass && Activity)
  163. if(JMethodID facebookGetFriends=jni->GetMethodID(ActivityClass, "facebookGetFriends", "()V"))
  164. jni->CallVoidMethod(Activity, facebookGetFriends);
  165. #elif IOS
  166. if(loggedIn())GetFriends();else{FlagEnable(Get, GET_FRIENDS); logIn();}
  167. #endif
  168. return T;
  169. }
  170. Str Facebook::userImageURL(ULong user_id, Int width, Int height)C
  171. {
  172. Str url=S+"http://graph.facebook.com/"+user_id+"/picture";
  173. Char par='?';
  174. if(width >0){url+=par; par='&'; url+= "width="; url+=width ;}
  175. if(height>0){url+=par; par='&'; url+="height="; url+=height;}
  176. return url;
  177. }
  178. void Facebook::openPage(C Str &page_name, C Str &page_id)
  179. {
  180. #if ANDROID
  181. if(!page_id.is() || !Explore(S+"fb://page/"+page_id))
  182. #elif IOS
  183. if(!page_id.is() || !Explore(S+"fb://profile/"+page_id))
  184. #endif
  185. if(page_name.is())Explore(S+"https://www.facebook.com/"+page_name);else
  186. if(page_id .is())Explore(S+"https://www.facebook.com/profile.php?id="+page_id);
  187. }
  188. void Facebook::post(C Str &message, C Str &url, C Str &image_url, C Str &title, C Str &desc, C Str &caption)
  189. {
  190. #if ANDROID
  191. JNI jni;
  192. if(jni && ActivityClass && Activity)
  193. if(JMethodID facebookPost=jni->GetMethodID(ActivityClass, "facebookPost", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"))
  194. if(JString j_message =JString(jni, message ))
  195. if(JString j_url =JString(jni, url ))
  196. if(JString j_image_url=JString(jni, image_url))
  197. if(JString j_title =JString(jni, title ))
  198. if(JString j_desc =JString(jni, desc ))
  199. if(JString j_caption =JString(jni, caption ))
  200. jni->CallVoidMethod(Activity, facebookPost, j_message(), j_url(), j_image_url(), j_title(), j_desc(), j_caption());
  201. #elif IOS
  202. if(FBSDKShareLinkContent *content=[[FBSDKShareLinkContent alloc] init])
  203. {
  204. NSURLAuto ns_url=url; content.contentURL=ns_url; // !! keep 'ns_url' as temp to be deleted later, in case 'content.contentURL' is a weak reference reusing its or NSString's memory
  205. content.quote =NSStringAuto(title.is() ? title : desc.is() ? desc : caption);
  206. if(FBSDKShareDialog *dialog=[[FBSDKShareDialog alloc] init])
  207. {
  208. dialog.fromViewController=ViewController;
  209. dialog.shareContent=content;
  210. dialog.delegate=GetAppDelegate();
  211. [dialog show];
  212. [dialog release];
  213. }
  214. [content release]; // release 'content' after 'dialog' finished, in case it has a weak reference
  215. }
  216. #endif
  217. }
  218. /******************************************************************************/
  219. } // namespace EE
  220. /******************************************************************************/
  221. #if ANDROID
  222. static Facebook::UserEmail Me;
  223. static Mems<Facebook::User > Friends;
  224. static Byte Result;
  225. static SyncLock Lock;
  226. static void UpdateMe () {SyncLocker locker(Lock); Swap(FB._me , Me );}
  227. static void UpdateFriends() {SyncLocker locker(Lock); Swap(FB._friends, Friends);}
  228. static void CallCallback () {if(void (*callback)(Facebook::RESULT result)=FB.callback)callback(Facebook::RESULT(Result));}
  229. extern "C" JNIEXPORT void JNICALL Java_com_esenthel_Native_facebookMe(JNIEnv *env, jclass clazz, jstring id, jstring name, jstring email)
  230. {
  231. JNI jni(env);
  232. SyncLocker locker(Lock);
  233. Me.id =TextULong(jni(id ));
  234. Me.name = jni(name ) ;
  235. Me.email= jni(email) ;
  236. App._callbacks.include(UpdateMe);
  237. }
  238. extern "C" JNIEXPORT void JNICALL Java_com_esenthel_Native_facebookFriends(JNIEnv *env, jclass clazz, jobject ids, jobject names)
  239. {
  240. JNI jni(env);
  241. Mems<Facebook::User> friends;
  242. if(JClass ArrayList=JClass(jni, ids))
  243. if(JMethodID size=jni->GetMethodID(ArrayList, "size", "()I"))
  244. if(JMethodID get =jni->GetMethodID(ArrayList, "get" , "(I)Ljava/lang/Object;"))
  245. {
  246. Int ids_elms=jni->CallIntMethod(ids , size),
  247. names_elms=jni->CallIntMethod(names, size);
  248. if( ids_elms==names_elms)
  249. {
  250. friends.setNum(ids_elms);
  251. REPA(friends)
  252. if(JString id =JString(jni, jni->CallObjectMethod(ids , get, jint(i))))
  253. if(JString name=JString(jni, jni->CallObjectMethod(names, get, jint(i))))
  254. {
  255. Facebook::User &f=friends[i];
  256. f.id =TextULong(id .str());
  257. f.name= name.str() ;
  258. }
  259. }
  260. }
  261. {
  262. SyncLocker locker(Lock);
  263. Swap(Friends, friends);
  264. App._callbacks.include(UpdateFriends);
  265. }
  266. }
  267. extern "C" JNIEXPORT void JNICALL Java_com_esenthel_Native_facebookPost(JNIEnv *env, jclass clazz, jint result)
  268. {
  269. if(FB.callback)
  270. {
  271. Result=result;
  272. App._callbacks.include(CallCallback);
  273. }
  274. }
  275. #endif
  276. /******************************************************************************/