20191024のAndroidに関する記事は3件です。

KudanARUnityのサンプルをAndroidで動かす

はじめに

この記事はUnity2018.2.21f1でKudanARUnityを動作させたの備忘録です。
今回はサンプル動作までを記載します。

動作環境
Unity2018.2.21f1
KudanARUnity V1.6.0
Android Studio v3.5.1
Glaxy feel SC-04J(Android8.0.0)

環境構築

  1. Unity、Androidのインストールについては割愛します。
  2. KudanARUnity V1.6.0を以下のページの枠で囲ったリンクからUnityパッケージを取得します。
    メールアドレスでの認証が必要で、入力したメールアドレスにダウンロードリンクのURLが添付されています。

ダウンロード先
kudan_download.png
3. ダウンロードしたKudan-UnityPlugin.zipを任意の箇所に展開します。

Unity Editorでのサンプル実行

  1. UnityのProjectを作成します。
  2. Unity Editorが起動したら、前項3. で展開したフォルダのKudanARUnity.unitypackageをProjectにD&D、Importします。
  3. Assets/KudanAR/Samples/KudanSample.unityをダブルクリックし、SampleSceneを開きます。
  4. HierarchyのKudan Bundle - With UIを開き、InspectorのKudan Tracker(Script)のEditor API Keyに、
    Kudanダウンロードページ APIキータブのUnity Editor Key(黒塗り部分)を入力します。(今回は公開されている開発用ライセンスキー使用します)

UnityEditorKey.png
5. API Keyに、Kudanダウンロードページ APIキータブのKudan AR SDK(黒塗り部分)を入力します。
APIKey.png
6. 再生ボタンを押すと、サンプルが実行されます。Assets/KudanAR/Samples/Textures/lego.jpgを表示し、カメラでとらえることで、モデルが表示されます。

SampleUnity.png

Android向けのビルドと実行

1. メニューバー File>BuildSettingsを選択し、ビルド設定を出します。
2. 赤枠①で囲ったAndroidを選択し、プラットフォームをAndroidに変更する。
3. 赤枠②で囲ったAdd Open Scenesをクリックし、サンプルシーンをビルド対象に追加する。(すでにチェックが入っているScenes/SampleSceneはチェックを外す)
4. 赤枠③で囲ったplayer Settingsをクリックし、player Settingsを表示する。
ビルドセッティング.png
4. 赤枠①で囲った、player Settings/Other Settings/Rendering/Multithreaded Renderingのチェックを外します。(理由はイマイチ分かっていませんが、この記事と同じ状況を解決するためにチェックを外しています。)
5. Package NameにKudanダウンロードページ APIキータブのKudan AR SDKのBundle IDを入力します。
(開発者ハブの画像ではeu.kudan.arとなっていますが、画像が古いです)

playerSettings.png
6. BuildSettingsのSwitch Platformをクリックし、プラットフォームをAndroidへ切り替えます。
7. Edit>Preferencesを開き、External ToolsのAndroid SDK/JDKのPATHを入力する。
Preferences.png
8. BuildSettingsのBuild And Runをクリックし、ビルドとアプリファイルの転送実行を行います。
 その結果、アプリでAssets/KudanAR/Samples/Textures/lego.jpgをキャプチャするとモデルが表示されます。
Screenshot_20191024-232133_kudan4Qiita.jpg

おわりに

今回はUnity2018.2.21f1でKudanARUnityのサンプルを動作させました。
次回はオリジナルのマーカー、3Dモデルを表示させます。

参考

The Kudan Developer Hub https://www.xlsoft.com/doc/kudan/ja/home_jp/
Kudan + UnityでAndroid向けマーカーレスARを試してみる(1) https://qiita.com/doatodarkness/items/be50fb420ad6ea1c79c0
【Unity初心者向け】Kudan AR SDKを使ったARアプリの開発方法とは? https://blog.codecamp.jp/unity-kudan-ar-sdk
AR KUDANでカメラが起動して居ない https://teratail.com/questions/103107

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

51歳からのプログラミング 備忘 FusedLocationProviderClientを常駐させる

FusedLocationProviderClientをForegroundSeriviceで常駐させる

androidDeveloperとgoogleApi様を参照してます。
あと、nyan様のサイトも、いっつも参照しています。ありがとうございます。


以下のサンプルコードは、androidのビルドバージョンはapi26以上です。

Manifest gradleの確認

Manifest
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application
    ...
    >
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version"/>
builed.gradle
dependencies {
    ...
    implementation 'com.google.android.gms:play-services-location:17.0.0'

Code

MainActivity
public class MainActivity extends AppCompatActivity {

    static TextView textView;
    static MainActivity mainActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Serviceで使うオブジェクトを取得してるよ
        textView = findViewById(R.id.textView);
        mainActivity = MainActivity.this;

        Intent intent = new Intent(this,MyService.class);
        startForegroundService(intent);
    }
}
MyService
public class MyService extends Service {

    TextView textView;
    FusedLocationProviderClient fusedLocationClient;

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // 位置情報を取り扱う時に使うオブジェクト を取得してるよ
        textView = MainActivity.textView;
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    }

    public int onStartCommand(Intent intent, int flags, int startId){
        // アプリを常駐させるためにForegorundServiseで通知処理をしまーす!
        // まずは、通知コンテンツ、チャンネル、重要度の作成ね!
        Notification notification;
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"id");
        Intent intentPending = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intentPending,0);
        notification = builder.setSmallIcon(R.drawable.notification_icon)
                              .setContentTitle("sampleApi")
                              .setContentText("sample")
                              .setContentIntent(pendingIntent)
                              .build();
        int importance = NotificationManager.IMPORTANCE_LOW;
        NotificationChannel channel = new NotificationChannel("id","name",importance);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);
        // ここまでが、通知コンテンツ、チャンネル、重要度の設定でした

        // 5秒以内に startForeground! 急げ!!
        startForeground(2,notification);

        locationManager();
        return START_STICKY;
    }

    private void locationManager(){
        // 定時的に位置を測定する、ていう設定ね
        LocationRequest request = LocationRequest.create();
            request.setInterval(1000*3);
            request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        // ACCESS_FIN_LOCATION は、ユーザーにとって危険のある設定なので
        // 許可を得るコードが必須です!
        // では許可チェックをしましょう
      if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            // 許可がなければ許可を求めてみます
            ActivityCompat.requestPermissions(MainActivity.mainActivity,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);
        }else{
            // 許可があるようなので、位置情報を取得していきます!
            fusedLocationClient.requestLocationUpdates(request,new LocationCallback(){
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    super.onLocationResult(locationResult);
                    // 例示的にlatitudeを表示します
                    String str = String.valueOf(locationResult.getLastLocation().getLatitude());
                    textView.setText(str);
                }
            }, Looper.getMainLooper());
        }
    }

    public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) {
        if (requestCode == 100) {
            // 省略
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

今回も、かなり時間を掛けました。位置情報を常駐的に取得するのって、僕にはハードル高すぎました。このコードを作るまでに約2週間。行ったり来たりを繰り返して、やっとでした~。

今回も亀の歩みですね。

亀の歩みでも、諦めないでもがき続けると、前進できるんだなって感じたよ。
無理かな無理かなと思っても、前進できるんだね。
まだまだ全然実力不足なんだけれど、面白い。すごく楽しい!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

51歳からのプログラミング 備忘 FusedLocationProviderClientをForegroundServiceで常駐させる

FusedLocationProviderClientをForegroundSeriviceで常駐させる

androidDeveloperとgoogleApi様を参照してます。
あと、nyan様のサイトも、いっつも参照しています。ありがとうございます。


以下のサンプルコードは、androidのビルドバージョンはapi26以上です。

Manifest gradleの確認

Manifest
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

builed.gradle
dependencies {
    ...
    implementation 'com.google.android.gms:play-services-location:17.0.0'

NotificationしないクラッシュCode

Notificationするとコードが長くなるので、まずはシンプルに動作確認するためのコードです。
起動すると位置情報を取得し始め、ボタンプッシュでサービスと位置情報取得を破棄。
5秒経つとクラッシュ

MainActivity
public class MainActivity extends AppCompatActivity {

    static MainActivity activity;
    static TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity = MainActivity.this;
        textView = findViewById(R.id.textView);
        Button button = findViewById(R.id.button);

        final Intent intent = new Intent(this,MyService.class);
        startForegroundService(intent);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(intent);
            }
        });
    }
}

MyService
public class MyService extends Service {

    MainActivity activity;
    TextView textView;
    FusedLocationProviderClient fusedLocationClient;
    LocationCallback myCallback;

    @Override
    public void onCreate() {
        super.onCreate();
        activity = MainActivity.activity;
        textView = MainActivity.textView;
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(activity);
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startId){
        // 本当ならここでNotificationを設定してstartForeground
        // でも見辛くなるので今回は省略
        myCallback = new myCallback(); // LocationCallback()インスタンス
        myCheckPermission();           // ActivityCompat.checkSelfPermission()
        myGetLocation();               // FusedLocationProviderClient.requestLocationUpdates(); 
        return START_STICKY;
    }

    // Manifestで設定したpermissonの ACCESS_FINE_LOCATIONってば
    // ユーザーデンジャラス なので、permissionの許諾が必要!
    public void myCheckPermission(){
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);
            // requestPermissions()で確認した内容は
            // 本当ならonRequestPermissionsResult()で処理するのですが省略です
        }else{
            return;
        }
    }

    public void myGetLocation(){
        // fusedLocationProviderClientの動作を設定
        LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setInterval(1000*3);
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        // では!位置情報を取得するよ!取得した情報はCallback()関数で扱います!
        fusedLocationClient.requestLocationUpdates(locationRequest,myCallback,null);
    }

    // MainActivityで、ストップボタンを押すと、Serviceが破棄されるようにしたので
    // その時に、onDestroyが呼ばれます
    // onDestroy()でfusedLocationProviderClientを破棄するよ!
    @Override
    public void onDestroy() {
        super.onDestroy();
        fusedLocationClient.removeLocationUpdates(myCallback);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    // LocationCallback()です。
    // 取得した位置情報を扱うのはこのクラス!
    class myCallback extends LocationCallback{
          @Override
          public void onLocationResult(LocationResult locationResult){
              super.onLocationResult(locationResult);
              // locationResultに位置情報があるので、それを使おう!
              double latitude = locationResult.getLastLocation().getLatitude();
              String strLatitude = String.valueOf(latitude);
              textView.setText(strLatitude);
        }
    }
}

常駐させ、緯度経度高度を取得するCode

Startボタンで位置情報取得と表示を常駐させます。
Stopボタンでサービスと位置情報取得を破棄します。
レッツゴー!

MainActivity
public class MainActivity extends AppCompatActivity {

    // Serviceから参照するUI部品をstaticに
    static MainActivity activity;
    static TextView textAlutitude;
    static TextView textLatitude;
    static TextView textLongitude;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // オブジェクトを取得!
        activity = MainActivity.this;
        textAlutitude = findViewById(R.id.textAltitude);
        textLatitude = findViewById(R.id.textLatitude);
        textLongitude = findViewById(R.id.textLongitude);
        Button btnStart= findViewById(R.id.btnStart);
        Button btnStop = findViewById(R.id.btnStop);


        // StartボタンでForagroundServiceスタート
        // StopボタンでForegroundServiceストップ
        //    ForegroundServiceストップでMyService.onDestroy()でFusedLocationProviderClientも破棄
        final Intent intent = new Intent(activity,MyService.class);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startForegroundService(intent);
            }
        });

        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(intent);
            }
        });

    }
}

MyService
public class MyService extends Service {

    // オブジェクトをグローバルに
    MainActivity activity;
    TextView textAltitude;
    TextView textLatitude;
    TextView textLongitude;
    FusedLocationProviderClient fusedLocationClient;
    LocationRequest locationRequest;
    LocationCallback locationCallback;

    @Override
    public void onCreate() {
        super.onCreate();

        // FusedLocationProviderClient は onCreate()で生成するみたい
        // オブジェクトを取得!
        activity = MainActivity.activity;
        textAltitude = MainActivity.textAlutitude;
        textLatitude = MainActivity.textLatitude;
        textLongitude = MainActivity.textLongitude;
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        // LocationRequestを設定しときます
        // 5秒ごとに詳細な位置情報を取得するように設定
        locationRequest = LocationRequest.create();
            locationRequest.setInterval(1000*5);
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    public int onStartCommand(Intent intent, int flags, int startId){
        // 常駐させたいので通知を出します

        // 通知コンテンツ、重要度、チャンネルを設定
        Notification notification;
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"id");
        Intent pIntent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,pIntent,0);
        notification = builder.setSmallIcon(R.drawable.notification_icon)
                              .setContentTitle("NotificationTitle")
                              .setContentText("NotificationText")
                              .setContentIntent(pendingIntent)
                              .build();
        int importance = NotificationManager.IMPORTANCE_LOW;
        NotificationChannel channel = new NotificationChannel("id","name",importance);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);

        // 5秒以内に startForeground !! 急げ!
        startForeground(1,notification);


        // LocationCallback()は、requestLocation,Update,removeで使うので、ここで作成しとく
        locationCallback = new LocationCallback(){
            @Override
            public void onLocationResult(LocationResult locationResult){
                super.onLocationResult(locationResult);
                String alti = String.valueOf(locationResult.getLastLocation().getAltitude());
                String lati = String.valueOf(locationResult.getLastLocation().getLatitude());
                String longi = String.valueOf(locationResult.getLastLocation().getLongitude());
                textAltitude.setText(alti);
                textLatitude.setText(lati);
                textLongitude.setText(longi);
            }
        };

        checkLocationPermission();
        return START_STICKY;
    }

    // 位置情報を取得
    private void locationUpdate(){
        fusedLocationClient.requestLocationUpdates(locationRequest,locationCallback,null);
    }

    // permission ACCESS_FINE_LOCATION はユーザーデンジャラスな設定なので許可を確認します
    public void checkLocationPermission(){
        if(ActivityCompat.checkSelfPermission(activity,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            // ACCESS_FINE_LOCATIONの許可がなければダイアログでユーザーに確認
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);
        }else{
            locationUpdate();
        }
    }

    // checkLocationPermission()のrequestPermissionsでユーザに確認した内容を処理します
    public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){
        if(requestCode == 100){
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                // 許可が得られたら
                locationUpdate();
            }else{
                // 許可が得られなかったら
                textAltitude.setText("No permission");
            }
        }
    }

    // Serviceが破棄されるときに、FusedLocationProviderClientも破棄
    @Override
    public void onDestroy() {
        super.onDestroy();
        fusedLocationClient.removeLocationUpdates(locationCallback);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

今回も、かなり時間を掛けました。位置情報を常駐的に取得するのって、僕にはハードル高すぎました。このコードを作るまでに約2週間。行ったり来たりを繰り返して、やっとでした~。

今回も亀の歩みですね。

亀の歩みでも、諦めないでもがき続けると、前進できるんだなって感じたよ。
無理かな無理かなと思っても、前進できるんだね。
まだまだ全然実力不足なんだけれど、面白い。すごく楽しい!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む