NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion とかでた。

[Developer Preview Android P] NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion; inside of com.google.android.gms [79478779] - Visible to Public - Issue Tracker

If your app is targeting API level 28 (Android 9.0) or above, you must include the following declaration within the element of AndroidManifest.xml.

対策は以下。AndroidManifest.xml。


<application ...
  ....
  <uses-library
      android:name="org.apache.http.legacy"
      android:required="false" />

Project Configuration  |  Maps SDK for Android  |  Google Developers

今回は、GoogleMap SDK vs API-28(9.0/Pie) だったけど、他でも出そうで、使えそう。


LINE Notify をつかってターミナルから送信する

使ってみる.

line-notify

コマンドラインから LINE にメッセージを送れる LINE Notify « LINE Engineers' Blog

とりあえず.


#!/bin/sh -x                                                                                                                                   

token=zbOIf0lthC34fLGsXuilN2WBIkbomhtKj18M1MP0B1g

while true
do
  read message
  curl https://notify-api.line.me/api/notify \
  -H "Authorization: Bearer ${token}" \
  -F "message=${message} https://goo.gl/lU0Kx6" \
  -F "imageThumbnail=https://pbs.twimg.com/profile_images/745806811597406210/HO0KCGf2_400x400.jpg" \
  -F "imageFullsize=http://developers.linecorp.com/blog/wp-content/uploads/2016/10/moon.png"
  echo
done

これはグループ向けのメッセージ通知用になるのかな.


Androidの 顔検出API 笑顔判定 は「笑いながら怒る人」をどう認識するか

こんなのが公開されています.

Google Play サービスでの顔検出 - Google Developer Japan Blog

顔認識をして「笑顔かどうか」の判定もできる.

image01

公式リファレンスをみてみると.

com.google.android.gms.vision.face.Face

public float getIsSmilingProbability ()

Returns a value between 0.0 and 1.0 giving a probability that the face is smiling.

This returns UNCOMPUTED_PROBABILITY if the probability was not computed. The probability is not computed if smile classification is not enabled via setClassificationType(int) or the required landmarks are not found. The LEFT_MOUTH, RIGHT_MOUTH, and NOSE_BASE landmarks are required to compute a smile probability.

Returns
the probability that the face is smiling

画像内の顔が笑顔であるかどうかを0から1の数値で取得できます.

Googleの公開しているサンプルをみてみると,

android-vision/FaceGraphic.java at master · googlesamples/android-vision

...
canvas.drawText("happiness: " + String.format("%.2f", face.getIsSmilingProbability()), x - ID_X_OFFSET, y - ID_Y_OFFSET, mIdPaint);
...

カメラに写っている画像にオーバーレイして「happiness: 0.92」のように「笑顔度」を表示します.
1に近いほど笑顔という判定です.

いくつか画像を試してみました.

20150928-145235

20150928-145057

20150928-145340

20150928-144823

20150928-144744

20150928-144605

20150928-144452

20150928-144225

20150928-144123

ほぼ正しく認識します.

では「笑いながら怒る人」はどうなるか.


20150928-145803

笑顔度 0.96 と判定されました.

声とセリフだけが「怒ってる」んですねこの芸って.


Youtube Player を Fragment に埋め込む

今や公開されてるAPIも多すぎて...

プレーヤーを WebView なしで埋め込みたいだけなのに...

YouTube_—_Google_Developers

YouTube — Google Developers

いちいち調べるのが面倒なので手順メモ.

・ libs/ 以下にタウンドードした jar を置く.

dependencies {
    compile files('libs/YouTubeAndroidPlayerApi.jar')
}

・ API11+ であれば全て使える.
DEVELOPER_KEY を取得する必要がある.

・ 画面の回転時の再読み込みを AndroidManifest.xml で考慮.

    <activity
        ...
        android:screenOrientation="nosensor"
        android:configChanges="orientation|screenSize|keyboardHidden”>

・ YouTubeFailureRecoveryActivity 作成する.

public abstract class YouTubeFailureRecoveryActivity extends YouTubeBaseActivity implements
    YouTubePlayer.OnInitializedListener {

  private static final int RECOVERY_DIALOG_REQUEST = 1;

  @Override
  public void onInitializationFailure(YouTubePlayer.Provider provider,
      YouTubeInitializationResult errorReason) {
    if (errorReason.isUserRecoverableError()) {
      errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST).show();
    } else {
      String errorMessage = String.format(getString(R.string.error_player), errorReason.toString());
      Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
    }
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RECOVERY_DIALOG_REQUEST) {
      // Retry initialization if user performed a recovery action
      getYouTubePlayerProvider().initialize(DeveloperKey.DEVELOPER_KEY, this);
    }
  }

  protected abstract YouTubePlayer.Provider getYouTubePlayerProvider();

}

・ Activity の親に YouTubeFailureRecoveryActivity を.

public class PlayerViewDemoActivity extends YouTubeFailureRecoveryActivity {

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.playerview_demo);

    // 処理開始
    YouTubePlayerView youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
    youTubeView.initialize(DeveloperKey.DEVELOPER_KEY, this);
  }

  @Override
  public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player,
      boolean wasRestored) {
    if (!wasRestored) {
      player.cueVideo("wKJ9KzGQq0w”); // 動画ID
    }
  }

  @Override
  protected YouTubePlayer.Provider getYouTubePlayerProvider() {
    return (YouTubePlayerView) findViewById(R.id.youtube_view); // プレーヤーID
  }

}

・ レイアウト (layout/playerview_demo.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

  <TextView
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_weight="1"
      android:textAppearance="@android:style/TextAppearance.Small"
      android:gravity="center"
      android:text="@string/playerview_text"/>

  <com.google.android.youtube.player.YouTubePlayerView
      android:id="@+id/youtube_view"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"/>

</LinearLayout>

という雰囲気.

Fragment 内に埋め込むなら, Activity が固定されてるものとして,

   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

     int section = getArguments().getInt(ARG_SECTION_NUMBER);
     View rootView = inflater.inflate(R.layout.playerview_demo, container, false);


     // 処理開始
     YouTubePlayerView youTubeView = (YouTubePlayerView) rootview.findViewById(R.id.youtube_view);

     youTubePlayerFragment.initialize(DeveloperKey.DEVELOPER_KEY,
                                      (YouTubePlayer.OnInitializedListener)getActivity());
   }

YouTube Android Player API - YouTube — Google Developers
サンプルアプリケーション - YouTube — Google Developers


MinSdkVersion を決めるときに素早くカバー率を算出する方法

「で, どれくらいのカバー率なの?」

「えーっと, Gingerbread なので 2.3 からなので API10から なのでー...」

とか, だるいすね.

で, 開くページが だいたいここ.

Dashboards___Android_Developers

Dashboards | Android Developers

で, こんな ダイアログが AndroidStudio にあったりします.

Screenshot_7_23_14__13_01

各OSバージョンの概要と説明ページへのリンク付きです.

Create_New_Project

新規プロジェクト作成からどうぞ.

Create_New_Project_and_Android_Studio