mirror of
https://github.com/purplecabbage/phonegap-plugins.git
synced 2026-04-24 03:00:11 -04:00
Merge pull request #226 from brianantonelli/master
Twitter iOS 5 Integration
This commit is contained in:
19
iPhone/Twitter/LICENSE.md
Normal file
19
iPhone/Twitter/LICENSE.md
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011 Brian Antonelli
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
43
iPhone/Twitter/README.md
Normal file
43
iPhone/Twitter/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
PhoneGap Twitter Plugin
|
||||
================================
|
||||
|
||||
The Twitter plugin for PhoneGap allows you to take advantage of the Twitter integration that ships with iOS 5. Please note that to use the APIs you must compile the application on the iOS 5 SDK. The plugin will not cause any issues if it is run on a pre-iOS 5 OS as long as you always validate that the Twitter SDK is available (see **Twitter.isTwitterAvailable()**)
|
||||
|
||||
This is licensed under MIT.
|
||||
|
||||
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
Download the latest version of PhoneGap from www.phonegap.com.
|
||||
|
||||
Create an iOS PhoneGap project (Android not yet supported)
|
||||
|
||||
Check out the /example/www/index.html to see how it works.
|
||||
|
||||
<pre>
|
||||
|-native
|
||||
| |-ios
|
||||
`-www
|
||||
`-TwitterPlugin.js
|
||||
</pre>
|
||||
|
||||
/native/ios is the native code for the plugin on ios.
|
||||
|
||||
/www/TwitterPlugin.js is the JavaScript code for the plugin
|
||||
|
||||
iOS (Mac OS X)
|
||||
===============
|
||||
|
||||
1. Create a basic PhoneGap iOS application. See http://www.phonegap.com/start/#ios-x4
|
||||
2. From the **PhoneGap Facebook Connect Plugin** folder copy the contents of the **native/ios** folder into your app in Xcode (usually in the **Plugins** folder group). Make sure it is added as a "group" (yellow folder)
|
||||
3. Find the PhoneGap.plist file in the project navigator, expand the "Plugins" sub-tree, and add a new entry. For the key, add **com.phonegap.twitter**, and its value will be **TwitterPlugin**
|
||||
4. From the **PhoneGap Twitter Plugin** folder copy the contents of the **www** folder into the **www** directory in Xcode (don't forget to add script tags in your index.html to reference any .js files copied over)
|
||||
5. Click on your project's icon (the root element) in Project Navigator, select your **Target**, and the **Build Phases** tab.
|
||||
6. From the **Build Phases** tab, expand **Link Binary With Libraries**, then click on the **+** button
|
||||
7. Select **Twitter.framework** and click Add
|
||||
8. for Xcode 4, you will need to build it once, and heed the warning - this is an Xcode 4 template limitation. The warning instructions will tell you to drag copy the **www** folder into the project in Xcode (add as a **folder reference** which is a blue folder).
|
||||
9. If you wish to allow users to share URLs and/or images you need to add a whitelist wildcard since you don't know which domains they'll reference. Simply add a wildcard entry (*) to external hosts whitelist (PhoneGap.plist/ExternalHosts).
|
||||
10. Run the application in Xcode.
|
||||
|
||||
If you have issues with the app crashing on iOS Simulator you may have a weak linking issue. For more information see: http://stackoverflow.com/questions/6738858/use-of-blocks-crashes-app-in-iphone-simulator-4-3-xcode-4-2-and-4-0-2
|
||||
59
iPhone/Twitter/example/www/demo.js
Normal file
59
iPhone/Twitter/example/www/demo.js
Normal file
@@ -0,0 +1,59 @@
|
||||
function onBodyLoad(){
|
||||
document.addEventListener("deviceready", onDeviceReady, false);
|
||||
}
|
||||
|
||||
function onDeviceReady(){
|
||||
console.log("onDeviceReady");
|
||||
TwitterDemo.setup();
|
||||
}
|
||||
|
||||
TwitterDemo = {
|
||||
$:function(id){
|
||||
return document.getElementById(id);
|
||||
},
|
||||
|
||||
log:function(s){
|
||||
TwitterDemo.$("log").innerHTML = s;
|
||||
},
|
||||
|
||||
setup:function(){
|
||||
var tests = ["isAvailable", "isSetup", "tweet", "timeline", "mentions"];
|
||||
for(var i=0, l=tests.length; i<l; i++){
|
||||
this.$(tests[i]).onclick = this[tests[i]];
|
||||
}
|
||||
},
|
||||
|
||||
isAvailable:function(){
|
||||
window.plugins.twitter.isTwitterAvailable(function(r){
|
||||
TwitterDemo.log("twitter available? " + r);
|
||||
});
|
||||
},
|
||||
|
||||
isSetup:function(){
|
||||
window.plugins.twitter.isTwitterSetup(function(r){
|
||||
TwitterDemo.log("twitter configured? " + r);
|
||||
});
|
||||
},
|
||||
|
||||
tweet:function(){
|
||||
window.plugins.twitter.sendTweet(
|
||||
function(s){ TwitterDemo.log("tweet success"); },
|
||||
function(e){ TwitterDemo.log("tweet failure: " + e); },
|
||||
"Tweety Poo",
|
||||
"https://github.com/brianantonelli",
|
||||
"http://zomgdinosaurs.com/zomg.jpg");
|
||||
},
|
||||
|
||||
timeline:function(){
|
||||
window.plugins.twitter.getPublicTimeline(
|
||||
function(s){ TwitterDemo.log("timeline success: " + JSON.stringify(s)); },
|
||||
function(e){ TwitterDemo.log("timeline failure: " + e); });
|
||||
},
|
||||
|
||||
mentions:function(){
|
||||
window.plugins.twitter.getMentions(
|
||||
function(s){ TwitterDemo.log("mentions success: " + JSON.stringify(s)); },
|
||||
function(e){ TwitterDemo.log("mentions failure: " + e); });
|
||||
}
|
||||
|
||||
};
|
||||
26
iPhone/Twitter/example/www/index.html
Normal file
26
iPhone/Twitter/example/www/index.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
|
||||
<meta charset="utf-8">
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="phonegap-1.1.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="TwitterPlugin.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="demo.js"></script>
|
||||
</head>
|
||||
<body onload="onBodyLoad()">
|
||||
<h1>Hey, it's Twitter on PhoneGap!</h1>
|
||||
<br />
|
||||
<ol>
|
||||
<li><a href="#" id="isAvailable">isAvailable</a></li>
|
||||
<li><a href="#" id="isSetup">isSetup</a></li>
|
||||
<li><a href="#" id="tweet">tweet</a></li>
|
||||
<li><a href="#" id="timeline">timeline</a></li>
|
||||
<li><a href="#" id="mentions">mentions</a></li>
|
||||
</ol>
|
||||
<div id="log" style="width:100%;height:200px;overflow:auto;background-color:#000;color:yellow;"></div>
|
||||
</body>
|
||||
</html>
|
||||
22
iPhone/Twitter/install
Normal file
22
iPhone/Twitter/install
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
def replace_in_file(filepath, regexp, *args, &block)
|
||||
content = File.read(filepath).gsub(regexp, *args, &block)
|
||||
File.open(filepath, 'wb') { |file| file.write(content) }
|
||||
end
|
||||
|
||||
file = File.expand_path(ARGV[0])
|
||||
platform = ( File.extension(file) == ".plist" ? "ios" : "android" )
|
||||
|
||||
if (platform == "ios")
|
||||
replace_in_file(file, /\s*<key>com.phonegap.twitter<\/key>\n/mi) do |match|
|
||||
""
|
||||
end
|
||||
replace_in_file(file, /\s*<string>TwitterPlugin<\/string>\n/mi) do |match|
|
||||
""
|
||||
end
|
||||
replace_in_file(file, /<key>Plugins<\/key>\n\s*<dict>/mi) do |match|
|
||||
"<key>Plugins</key>\n\t<dict>\n\t\t<key>com.phonegap.twitter</key>\n\t\t<string>TwitterPlugin</string>"
|
||||
end
|
||||
elsif (platform == "android")
|
||||
end
|
||||
32
iPhone/Twitter/native/ios/TwitterPlugin.h
Normal file
32
iPhone/Twitter/native/ios/TwitterPlugin.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// TwitterPlugin.h
|
||||
// TwitterPlugin
|
||||
//
|
||||
// Created by Antonelli Brian on 10/13/11.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Twitter/Twitter.h>
|
||||
#import <Accounts/Accounts.h>
|
||||
#ifdef PHONEGAP_FRAMEWORK
|
||||
#import <PhoneGap/PGPlugin.h>
|
||||
#else
|
||||
#import "PGPlugin.h"
|
||||
#endif
|
||||
|
||||
@interface TwitterPlugin : PGPlugin{
|
||||
}
|
||||
|
||||
- (void) isTwitterAvailable:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
|
||||
- (void) isTwitterSetup:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
|
||||
- (void) sendTweet:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
|
||||
- (void) getPublicTimeline:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
|
||||
- (void) getMentions:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
|
||||
- (void) performCallbackOnMainThreadforJS:(NSString*)js;
|
||||
|
||||
@end
|
||||
181
iPhone/Twitter/native/ios/TwitterPlugin.m
Normal file
181
iPhone/Twitter/native/ios/TwitterPlugin.m
Normal file
@@ -0,0 +1,181 @@
|
||||
//
|
||||
// TwitterPlugin.m
|
||||
// TwitterPlugin
|
||||
//
|
||||
// Created by Antonelli Brian on 10/13/11.
|
||||
//
|
||||
|
||||
#import "TwitterPlugin.h"
|
||||
#ifdef PHONEGAP_FRAMEWORK
|
||||
#import <PhoneGap/JSON.h>
|
||||
#else
|
||||
#import "JSON.h"
|
||||
#endif
|
||||
|
||||
#define TWITTER_URL @"http://api.twitter.com/1/"
|
||||
|
||||
@implementation TwitterPlugin
|
||||
|
||||
- (void) isTwitterAvailable:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options{
|
||||
NSString *callbackId = [arguments objectAtIndex:0];
|
||||
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
|
||||
BOOL twitterSDKAvailable = tweetViewController != nil;
|
||||
|
||||
// http://brianistech.wordpress.com/2011/10/13/ios-5-twitter-integration/
|
||||
if(tweetViewController != nil){
|
||||
[tweetViewController release];
|
||||
}
|
||||
|
||||
[super writeJavascript:[[PluginResult resultWithStatus:PGCommandStatus_OK messageAsInt:twitterSDKAvailable ? 1 : 0] toSuccessCallbackString:callbackId]];
|
||||
}
|
||||
|
||||
- (void) isTwitterSetup:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options{
|
||||
NSString *callbackId = [arguments objectAtIndex:0];
|
||||
BOOL canTweet = [TWTweetComposeViewController canSendTweet];
|
||||
|
||||
[super writeJavascript:[[PluginResult resultWithStatus:PGCommandStatus_OK messageAsInt:canTweet ? 1 : 0] toSuccessCallbackString:callbackId]];
|
||||
}
|
||||
|
||||
- (void) sendTweet:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options{
|
||||
// arguments: callback, tweet text, url attachment, image attachment
|
||||
NSString *callbackId = [arguments objectAtIndex:0];
|
||||
NSString *tweetText = [arguments objectAtIndex:1];
|
||||
NSString *urlAttach = [arguments objectAtIndex:2];
|
||||
NSString *imageAttach = [arguments objectAtIndex:3];
|
||||
|
||||
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
|
||||
[tweetViewController setInitialText:tweetText];
|
||||
|
||||
BOOL ok = YES;
|
||||
NSString *errorMessage;
|
||||
|
||||
if(urlAttach != nil){
|
||||
ok = [tweetViewController addURL:[NSURL URLWithString:urlAttach]];
|
||||
if(!ok){
|
||||
errorMessage = @"URL too long";
|
||||
}
|
||||
}
|
||||
|
||||
if(imageAttach != nil){
|
||||
// Note that the image is loaded syncronously
|
||||
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageAttach]]];
|
||||
ok = [tweetViewController addImage:img];
|
||||
if(!ok){
|
||||
errorMessage = @"Image could not be added";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!ok){
|
||||
[super writeJavascript:[[PluginResult resultWithStatus:PGCommandStatus_ERROR
|
||||
messageAsString:errorMessage] toErrorCallbackString:callbackId]];
|
||||
}
|
||||
else{
|
||||
[tweetViewController setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
|
||||
switch (result) {
|
||||
case TWTweetComposeViewControllerResultDone:
|
||||
[super writeJavascript:[[PluginResult resultWithStatus:PGCommandStatus_OK] toSuccessCallbackString:callbackId]];
|
||||
break;
|
||||
case TWTweetComposeViewControllerResultCancelled:
|
||||
default:
|
||||
[super writeJavascript:[[PluginResult resultWithStatus:PGCommandStatus_ERROR
|
||||
messageAsString:@"Cancelled"] toErrorCallbackString:callbackId]];
|
||||
break;
|
||||
}
|
||||
|
||||
[super.appViewController dismissModalViewControllerAnimated:YES];
|
||||
|
||||
}];
|
||||
|
||||
[super.appViewController presentModalViewController:tweetViewController animated:YES];
|
||||
}
|
||||
|
||||
[tweetViewController release];
|
||||
}
|
||||
|
||||
|
||||
- (void) getPublicTimeline:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options{
|
||||
NSString *callbackId = [arguments objectAtIndex:0];
|
||||
NSString *url = [NSString stringWithFormat:@"%@statuses/public_timeline.json", TWITTER_URL];
|
||||
|
||||
TWRequest *postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:url] parameters:nil requestMethod:TWRequestMethodGET];
|
||||
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
|
||||
NSString *jsResponse;
|
||||
|
||||
if([urlResponse statusCode] == 200) {
|
||||
|
||||
NSString *dataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
|
||||
NSDictionary *dict = [dataString JSONValue];
|
||||
jsResponse = [[PluginResult resultWithStatus:PGCommandStatus_OK messageAsDictionary:dict] toSuccessCallbackString:callbackId];
|
||||
[dataString release];
|
||||
}
|
||||
else{
|
||||
jsResponse = [[PluginResult resultWithStatus:PGCommandStatus_ERROR
|
||||
messageAsString:[NSString stringWithFormat:@"HTTP Error: %i", [urlResponse statusCode]]]
|
||||
toErrorCallbackString:callbackId];
|
||||
}
|
||||
|
||||
[self performCallbackOnMainThreadforJS:jsResponse];
|
||||
}];
|
||||
|
||||
[postRequest release];
|
||||
}
|
||||
|
||||
- (void) getMentions:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options{
|
||||
NSString *callbackId = [arguments objectAtIndex:0];
|
||||
NSString *url = [NSString stringWithFormat:@"%@statuses/mentions.json", TWITTER_URL];
|
||||
|
||||
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
|
||||
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
|
||||
|
||||
[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
|
||||
if(granted) {
|
||||
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
|
||||
// making assumption they only have one twitter account configured, should probably revist
|
||||
if([accountsArray count] > 0) {
|
||||
TWRequest *postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:url] parameters:nil requestMethod:TWRequestMethodGET];
|
||||
[postRequest setAccount:[accountsArray objectAtIndex:0]];
|
||||
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
|
||||
NSString *jsResponse;
|
||||
if([urlResponse statusCode] == 200) {
|
||||
NSString *dataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
|
||||
NSDictionary *dict = [dataString JSONValue];
|
||||
jsResponse = [[PluginResult resultWithStatus:PGCommandStatus_OK messageAsDictionary:dict] toSuccessCallbackString:callbackId];
|
||||
[dataString release];
|
||||
}
|
||||
else{
|
||||
jsResponse = [[PluginResult resultWithStatus:PGCommandStatus_ERROR
|
||||
messageAsString:[NSString stringWithFormat:@"HTTP Error: %i", [urlResponse statusCode]]]
|
||||
toErrorCallbackString:callbackId];
|
||||
}
|
||||
|
||||
[self performCallbackOnMainThreadforJS:jsResponse];
|
||||
}];
|
||||
[postRequest release];
|
||||
}
|
||||
else{
|
||||
NSString *jsResponse = [[PluginResult resultWithStatus:PGCommandStatus_ERROR
|
||||
messageAsString:@"No Twitter accounts available"]
|
||||
toErrorCallbackString:callbackId];
|
||||
[self performCallbackOnMainThreadforJS:jsResponse];
|
||||
}
|
||||
}
|
||||
else{
|
||||
NSString *jsResponse = [[PluginResult resultWithStatus:PGCommandStatus_ERROR
|
||||
messageAsString:@"Access to Twitter accounts denied by user"]
|
||||
toErrorCallbackString:callbackId];
|
||||
[self performCallbackOnMainThreadforJS:jsResponse];
|
||||
}
|
||||
}];
|
||||
|
||||
[accountStore release];
|
||||
}
|
||||
|
||||
// The JS must run on the main thread because you can't make a uikit call (uiwebview) from another thread (what twitter does for calls)
|
||||
- (void) performCallbackOnMainThreadforJS:(NSString*)javascript{
|
||||
[super performSelectorOnMainThread:@selector(writeJavascript:)
|
||||
withObject:javascript
|
||||
waitUntilDone:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
15
iPhone/Twitter/package.json
Normal file
15
iPhone/Twitter/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"author": "Brian Antonelli",
|
||||
"name": "com.phonegap.twitter",
|
||||
"description": "PhoneGap Twitter Plugin",
|
||||
"version": "0.0.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/brianantonelli/phonegap-plugin-twitter.git"
|
||||
},
|
||||
"engines": {
|
||||
"phonegap": "1.0.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"development_dependencies": {}
|
||||
}
|
||||
29
iPhone/Twitter/www/TwitterPlugin.js
Normal file
29
iPhone/Twitter/www/TwitterPlugin.js
Normal file
@@ -0,0 +1,29 @@
|
||||
var Twitter = function(){};
|
||||
|
||||
Twitter.prototype.isTwitterAvailable = function(response){
|
||||
PhoneGap.exec(response, null, "com.phonegap.twitter", "isTwitterAvailable", []);
|
||||
};
|
||||
|
||||
Twitter.prototype.isTwitterSetup = function(response){
|
||||
PhoneGap.exec(response, null, "com.phonegap.twitter", "isTwitterSetup", []);
|
||||
};
|
||||
|
||||
Twitter.prototype.sendTweet = function(success, failure, tweetText, urlAttach, imageAttach){
|
||||
if(typeof urlAttach === "undefined") urlAttach = "";
|
||||
if(typeof imageAttach === "undefined") imageAttach = "";
|
||||
|
||||
PhoneGap.exec(success, failure, "com.phonegap.twitter", "sendTweet", [tweetText, urlAttach, imageAttach]);
|
||||
};
|
||||
|
||||
Twitter.prototype.getPublicTimeline = function(success, failure){
|
||||
PhoneGap.exec(success, failure, "com.phonegap.twitter", "getPublicTimeline", []);
|
||||
};
|
||||
|
||||
Twitter.prototype.getMentions = function(success, failure){
|
||||
PhoneGap.exec(success, failure, "com.phonegap.twitter", "getMentions", []);
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if(!window.plugins) window.plugins = {};
|
||||
window.plugins.twitter = new Twitter();
|
||||
});
|
||||
Reference in New Issue
Block a user