LoginSignup
23
25

More than 5 years have passed since last update.

AndroidでFacebookみたいにOGP情報を取得する

Last updated at Posted at 2014-08-19

AndroidでFacebookみたいにOGP情報を取得する方法です。

こんなやつです。
facebookogp.png

スクレイピングにはjsoupを使います。HTML5などにも対応していて便利。

jsoup

build.gradle

dependencies {
    compile 'org.jsoup:jsoup:1.7.3'
}
AndroidManifest.xml
<!-- 追記する -->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
Ogp.java
/**
 * OGP取得クラス
 * @author shikato
 *
 */
public class Ogp {

    private Context _mContext = null;
    private Handler _mHandler = null;
    private String _mUa = "Mozilla/5.0 (Linux; Android 4.4.2; SOT21 Build/17.1.1.C.1.45) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Safari/537.36";

    /**
     * Ogpリスナー
     * @author shikato
     */
    public interface OgpListener {

        public static final int NETWORK_ERROR = -1;
        public static final int UNSUPPORTED_MIME_TYPE_ERROR = -2;
        public static final int UNKNOWN_HOST_ERROR = -3;
        public static final int TIMEOUT_ERROR = -4;
        public static final int UNKNOWN_ERROR = -5;

        public void onSuccess( final OgpData aOgpData );

        public void onError( final int aErrorCode );

        public void onHttpError( final int aHttpStatusCode );
    }

    public Ogp( final Context aContext ) {

        _mContext = aContext.getApplicationContext();
        _mHandler = new Handler();
    }

    public Ogp( final Context aContext, final String aUa ) {

        _mContext = aContext.getApplicationContext();
        _mHandler = new Handler();
        _mUa = aUa;
    } 

    public void getOgp( final String aUrl, final OgpListener aListener ) {

        // ネットワークに接続しているかどうか 
        if ( !_isConnectedNetwork( _mContext ) ) {

            aListener.onError( OgpListener.NETWORK_ERROR );

            return;
        }

        ( new Thread( new Runnable() {

            @Override
            public void run() { 

                try {

                    final Connection.Response response =
                            Jsoup.connect( aUrl ).userAgent( _mUa ).timeout( 5000 ).execute();

                    final int statusCode = response.statusCode();

                    if ( statusCode != 200 ) {

                        _mHandler.post( new Runnable() {

                            @Override
                            public void run() {

                                aListener.onHttpError( statusCode );
                            }  
                        } );

                        return;    
                    }

                    final Document document = response.parse();
                    final OgpData ogpData = new OgpData();

                    ogpData.setUrl( aUrl );
                    ogpData.setTitle( _getTitle( document ) );
                    ogpData.setDescription( _getDescription( document ) );
                    ogpData.setImage( _getImage( document, aUrl ) );

                    _mHandler.post( new Runnable() {

                        @Override
                        public void run() {

                            aListener.onSuccess( ogpData );
                        }
                    } );

                } catch ( UnsupportedMimeTypeException e ) {

                    e.printStackTrace();

                    _postError( OgpListener.UNSUPPORTED_MIME_TYPE_ERROR, aListener );

                } catch ( UnknownHostException e ) {

                    e.printStackTrace();

                    _postError( OgpListener.UNKNOWN_HOST_ERROR, aListener );

                } catch ( SocketTimeoutException e ) {

                    e.printStackTrace();

                    _postError( OgpListener.TIMEOUT_ERROR, aListener );

                } catch ( Exception e ) {

                    e.printStackTrace();

                    _postError( OgpListener.UNKNOWN_ERROR, aListener );
                }
            }

        } ) ).start();
    }

    private String _getTitle( final Document aDocument ) {

        // OGPタイトル取得
        final Elements elements = aDocument.getElementsByAttributeValue( "property", "og:title" );

        if ( elements.hasAttr( "content" ) ) {

            return elements.attr( "content" );
        }

        // OGPセットされてない場合はtitleタグの内容を返す
        final String title = aDocument.title();

        if ( title == null ) {

            return "";
        }

        return title;
    }

    private String _getDescription( final Document aDocument ) {

        // OGP description取得 
        Elements elements = aDocument.getElementsByAttributeValue( "property", "og:description" );

        if ( elements.hasAttr( "content" ) ) {

            return elements.attr( "content" );
        }

        // OGPセットされてない場合はdescriptionタグの内容を返す
        elements = aDocument.getElementsByAttributeValue( "property", "description" );

        if ( elements.hasAttr( "content" ) ) {

            return elements.attr( "content" );
        }

        return "";
    }

    private String _getImage( final Document aDocument, final String aUrl ) {

        // OGP image取得 
        Elements elements = aDocument.getElementsByAttributeValue( "property", "og:image" );

        if ( elements.hasAttr( "content" ) ) {

            String imgPath = elements.attr( "content" );

            // http or httpsで始まるフルパスを取得する
            imgPath = _getFullPath( imgPath, aUrl );

            if ( imgPath != null ) {

                return imgPath;
            }
        }

        // OGPない場合はitemprop属性を見る
        elements = aDocument.getElementsByAttributeValue( "itemprop", "image" );

        for ( Element element : elements ) {

            String imgPath = element.attr( "content" );

            imgPath = _getFullPath( imgPath, aUrl );

            if ( imgPath == null ) {

                continue;
            }

            return imgPath;
        }

        // itemprop属性も無い場合はimgタグを見る
        // リクエスト増えるけどサイズやMIMEタイプ見たりしても良いかも
        elements = aDocument.getElementsByTag( "img" );

        for ( Element element : elements ) {

            String imgPath = element.attr( "src" );

            imgPath = _getFullPath( imgPath, aUrl );

            if ( imgPath == null ) {

                continue;
            }

            return imgPath;
        }

        return "";
    }

    private String _getFullPath( final String aImagePathStr, final String aOgpUrlStr ) {

        if ( aImagePathStr.indexOf( "http://" ) == 0 || aImagePathStr.indexOf( "https://" ) == 0 ) {

            return aImagePathStr;
        }

        try {

            final URI ogpUri = new URI( aOgpUrlStr ); 

            final URI imgUri = ogpUri.resolve( aImagePathStr ); 

            return imgUri.toString();

        } catch ( URISyntaxException e ) {

            return null;
        }
    }

    private void _postError( final int aErrorCode, final OgpListener aListener ) {

        _mHandler.post( new Runnable() {

            @Override
            public void run() {

                aListener.onError( aErrorCode );
            }
        } );
    }

    private static boolean _isConnectedNetwork( final Context aContext ) {

        final ConnectivityManager connectivityManager =
                (ConnectivityManager)aContext.getSystemService( Context.CONNECTIVITY_SERVICE );

        final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        if ( networkInfo != null && networkInfo.isConnected() ) {

            return true;
        }

        return false;
    }
}
OgpData.java
/**
 * OGPデータクラス
 * @author shikato
 *
 */
public class OgpData {

    private String _mUrl;

    private String _mTitle;

    private String _mDescription;

    private String _mImage;

    public String getUrl() {

        return _mUrl;
    }

    public void setUrl( final String aUrl ) {

        _mUrl = aUrl;
    }

    public String getTitle() {

        return _mTitle;
    }

    public void setTitle( final String aTitle ) {

        _mTitle = aTitle;
    }

    public String getDescription() {

        return _mDescription;
    }

    public void setDescription( final String aDescription ) {

        _mDescription = aDescription;
    }

    public String getImage() {

        return _mImage;
    }

    public void setImage( final String aImage ) {

        _mImage = aImage;
    }
}
ex.
public class SampleActivity extends Activity {

    @Override
    protected void onCreate( final Bundle aSavedInstanceState ) {

        super.onCreate( aSavedInstanceState );
        setContentView( R.layout.activity_my ); 

        final Ogp ogp = new Ogp( getApplicationContext() );

        ogp.getOgp( "http://sample.com", new Ogp.OgpListener() {

            @Override
            public void onSuccess( final OgpData aOgpData ) {

                // 成功時の処理
                // 良い感じにOGPを表示する
            }

            @Override
            public void onError( final int aErrorCode ) {

                // エラー時の処理
            }

            @Override
            public void onHttpError( final int aHttpStatusCode ) {

                // HTTPエラー時の処理
            }
        } );
    }  
}

Gist

画像の表示にはメモリやディスクキャッシュを細かく設定できる、Universal Image Loader for Androidが便利。

23
25
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
25