Twitter」タグアーカイブ

[iOS]:アプリから画像付きのツイートをする

iOSアプリから、ツイッター・Facebookなど各種SNSやメール・メッセージなどで、画像付きのシェアをする方法です。

SLComposeViewControllerを使う場合はTwitter・Facebookなどの限られたSNSにしかポストできず、SNSを指定する方法も自前で実装する必要があります。

一方、UIActivityViewControllerを使うと、利用出来るSNS・ツールなどの選択画面が自動的に用意されます。

UIActivityViewControllerを使用した場合

UIActivityViewControllerを使用した場合

いずれの方法もiOS6.0以降で、Social.frameworkが必要になります。

#import <Social/Social.h>

@interface SNSController : NSObject <UIActionSheetDelegate>

-(void) share:(UIViewController *)viewController : (NSString *)_txt : (NSString *)_hashTag : (NSString *)_url : (NSString *)_path;
@end

@implementation SNSController {
    UIViewController *viewController;
    NSString *txt, *hashTag;
    NSURL *url;
    UIImage *image;
}

-(void) share:(UIViewController *)_viewController : (NSString *)_txt : (NSString *)_hashTag : (NSString *)_url : (NSString *)_path {
    viewController = _viewController;
    txt = _txt;
    hashTag = _hashTag;
    url = [NSURL URLWithString:_url];
    if (_path) image = [UIImage imageWithContentsOfFile:_path];
    
    UIActionSheet *actionServiceType = [[UIActionSheet alloc] initWithTitle:@"Share result on ..." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Twitter", @"Facebook", nil];
    [actionServiceType showInView:viewController.view];
}

#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
    NSString *serviceType = nil;
    if (buttonIndex == 0) serviceType = SLServiceTypeTwitter;
    else if (buttonIndex == 1) serviceType = SLServiceTypeFacebook;
    
    if (serviceType) [self compose:serviceType];
}

- (void)compose:(NSString *)serviceType {
    NSString *str;
    if (serviceType == SLServiceTypeTwitter) str = [txt stringByAppendingFormat:@" %@", hashTag];
    else if (serviceType == SLServiceTypeFacebook) str = txt;
    else str = txt;

    SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:serviceType];
    if (image) [controller addImage:image];
    [controller addURL:url];
    [controller setInitialText:str];
    [viewController presentViewController:controller animated:YES completion:nil];
}
@end
#import <Social/Social.h>

@interface SNSController : NSObject <UIActivityItemSource>

-(void) share:(UIViewController *)viewController : (NSString *)_txt : (NSString *)_hashTag : (NSString *)_url : (NSString *)_path;
@end

@implementation SNSController {
    NSString *txt, *hashTag;
}

-(void) share:(UIViewController *)viewController : (NSString *)_txt : (NSString *)_hashTag : (NSString *)_url : (NSString *)_path {
    txt = _txt;
    hashTag = _hashTag;
    NSURL *url = [NSURL URLWithString:_url];

    NSArray *array;
    float version = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (version < 7.0) {
        array = [NSArray arrayWithObjects:self, url, nil];
    } else {
        txt = [txt stringByAppendingFormat:@" %@", url];
        array = [NSArray arrayWithObjects:self, nil];
    }

    if (_path) {
        UIImage *image = [UIImage imageWithContentsOfFile:_path];
        if (image) array = [NSArray arrayWithObjects:self, image, nil];
    }
    
    UIActivityViewController *avc = [[UIActivityViewController alloc] initWithActivityItems:array applicationActivities:nil];
    [viewController presentViewController:avc animated:YES completion:nil];
}

#pragma mark - UIActivityItemSource
-(id) activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
    if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
        return [NSString stringWithFormat:@"%@ %@", txt, hashTag];
    }
    return txt;
}

-(id) activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController {
    return txt;
}
@end

iOS6.x台とiOS7.0以降で分岐させているのは、iOS7.0ではUIActivityViewControllerにNSURLを放り込むと、実行時にブラウザに飛んでしまうようになったためです。

[Android]:アプリから画像付きのツイートをする

AndroidアプリからIntentを使って、各種SNSに画像付きでシェアする実装例です。
一部の機種でしか動作確認できておらず、不完全であることをご了承下さい。

public void share(final Activity activity, final String text, final String path) {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    intent.putExtra(Intent.EXTRA_TEXT, text);
    if (path != null) intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + path));

    try {
        activity.startActivity(intent);
    } catch (ActivityNotFoundException e) {
        Toast.makeText(activity, "Client not found.", Toast.LENGTH_LONG).show();
    }
}

“text/plain”の内容を開く事ができるアプリの一覧が表示され、選択することにより各アプリにテキスト・画像がプリセットされた状態で開きます。

Intent一覧  Intent-Twitter  Intent-Facebook

ただしFacebookに関しては、仕様によりURLしかシェアできません。
またGmailに関しては、送信画面では画像が添付されているように見えますが、
実際に送信するとメールに画像は添付されません。

Gmailで画像が添付されるようにするには以下のように実装します。

public void share(final Activity activity, final String text, final String path) {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    intent.putExtra(Intent.EXTRA_TEXT, text);

    try {
        String filepath = Images.Media.insertImage(activity.getContentResolver(), path, "screenshot.png", null);
        intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(filepath));

        activity.startActivity(intent);
    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (ActivityNotFoundException e) {
        Toast.makeText(activity, "Client not found.", Toast.LENGTH_LONG).show();
    }
}

ただし、こうすると画像のコピーが作成され、明示的に削除をしない限りストレージに残り続けてしまいます。

Androidネイティブの開発に関しては全くの無知な私に、正しい実装法をご教授下さる方、お待ちしております!