java - Android Studio 上 AndAR(r205) 示例代码 "nmatsui/AR_Speeker"的奇怪行为

标签 java android eclipse andar

我尝试复制/迁移松井伸行先生在GitHub上上传的AndAR示例代码“nmatsui/AR_Speeker”,可以从here下载,我在 Android Studio (0.4.0) 上遇到了奇怪的行为。提供的代码工作正常。在 Eclipse(朱诺)中。

问题是我可以在 Android Studio 中编译而不会出现错误,但是当我调试到我的设备时,我得到黑屏并且根本没有任何功能 - 没有相机预览 - 没有模型加载。

此外,只要我能够以我有限的 java/android 知识解释这些错误,我就不会在 logcat 中遇到 fatal error 。

我在这里寻求别人的帮助,因为我需要让这段代码在 Android Studio 上运行,这样我就可以在大约 2 周的期限内基于它构建一个锻炼应用程序。

是否有人成功尝试为 Android Studio 复制/迁移“nmatsui/AR_SPeeker”,并且可以为我提供 GitHub 链接?

提前谢谢大家。

这是项目(结构):

enter image description here

这是我的 Android list (我遇到了 @drawable/icon 的错误,我暂时通过工具修复了该错误:ignore="MissingApplicationIcon"):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="jp.co.tis.stc"
  android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" android:maxSdkVersion="10"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" />
<supports-screens android:smallScreens="true"
    android:normalScreens="true"
    android:largeScreens="true"
    android:anyDensity="true" />

<application
    android:allowBackup="true"
    android:label="AR_Speaker"
    tools:ignore="MissingApplicationIcon">
    <activity android:name=".AR_SpeakerActivity"
              android:clearTaskOnLaunch="true"
              android:noHistory="true"
              android:screenOrientation="landscape"
              android:label="AR_Speaker">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

这是 build.gradle.xml:

buildscript {
repositories {
    mavenCentral()
}
dependencies {
    classpath 'com.android.tools.build:gradle:0.7.+'
 }
}
apply plugin: 'android'
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile files('libs/AndAR.jar')}
android {
compileSdkVersion 19
buildToolsVersion "19.0.2"

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }

    instrumentTest.setRoot('tests')
   }
  }

我在第 23 行和第 24 行收到“Cannot assign ArrayList<String> to "HashSet<Iterable<?>> ”警告。

这里是主要 Activity AR_SpeakerActivity(所有注释都是日语,我无法解释!),其中显示第 123、125 行已弃用“getWidth()”和“getHeight()”的警告。 我该怎么办?

按照 Raghav Sood 在第 123-124 行(现在为 125-133)中的建议进行编辑。仍然出现黑屏。 我还应该在这段代码 fragment 中使用“Ratio”吗?我应该如何编辑它?

package jp.co.tis.stc;

import android.app.ProgressDialog;
import android.hardware.Camera.Size;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.WindowManager;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import edu.dhbw.andar.ARToolkit;
import edu.dhbw.andar.AndARActivity;
import edu.dhbw.andobjviewer.graphics.LightingRenderer;
import jp.co.tis.stc.player.Elaine;
import jp.co.tis.stc.player.Porl;
import util.MarkerInfo;

public class AR_SpeakerActivity extends AndARActivity {
private static final float THRESHOLD = 50.0f;
// タップ位置とマーカー中心のズレの許容範囲 ピ   ク  セル)
private ARToolkit arToolkit;
private GestureDetector gd;
private SoundPool sp;
private float xRatio;
private float yRatio;

private List<PlayerBase> players = new ArrayList<PlayerBase>();

@SuppressWarnings("unchecked")
// AsyncTaskへplayersを可変引数として渡す際に、型パラメータが落ちるという警告を抑制
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    gd = new GestureDetector(this, onGestureListener); // タップを検出するDetector

    super.setNonARRenderer(new LightingRenderer());
    arToolkit = super.getArtoolkit();

    players.add(new Porl());
// マーカー・3Dモデル・音声・動作を定義したPlayer "Porl" を追加
    players.add(new Elaine());
// マーカー・3Dモデル・音声・動作を定義したPlayer "Elaine" を追加

    new ModelLoader().execute(players); // 非同期処理でPlayerを読み込み
}

@Override
protected void onResume() {
    super.onResume();
    // Activityが前面になったら音声再生用にSoundPoolを作成
    sp = new SoundPool(players.size(), AudioManager.STREAM_MUSIC, 0);
    sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
        // SoundPoolの初期化が完了した際に呼ばれるコールバック関数を定義
        @Override
        public void onLoadComplete(SoundPool sp, int soundId, int status) {
        Log.d("AR_Speaker", String.format("load complete soundId=%d:status=%d", soundId, status));
            for (PlayerBase player : players) {
                player.notifyLoadComplete(soundId);
// Playerに「このsoundIdの初期化が完了したよ」と通知
            }
        }
    });
    for (PlayerBase player : players) {
        player.loadSound(this, sp); // すべてのPlayerの音声を読み込む
    }
}

@Override
protected void onPause() {
    sp.release(); // Activityが背面にまわったらSoundPoolを解放
    super.onPause();
}

@Override
public void uncaughtException(Thread thread, Throwable ex) {
    Log.e("AR_Speaker", ex.getMessage());
    finish();
}

// 非同期処理でPlayerを読み込み
private class ModelLoader extends AsyncTask<List<PlayerBase>, Void, Void> {
    private ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // 非同期処理開始前にプログレスダイアログを表示
        progressDialog = new ProgressDialog(AR_SpeakerActivity.this);
         progressDialog.setMessage(AR_SpeakerActivity.this.getString(R.string.loading));
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.show();
    }

    @Override
    protected Void doInBackground(List<PlayerBase>... args) {
        try {
            for (PlayerBase player : args[0]) {
                // Playerの3DモデルをARObjectとしてARToolkitへ登録する
                arToolkit.registerARObject(player.getModel3d(getResources()));
            }
        } catch (Exception e) {
            Log.e("AR_Speaker", e.getMessage());
            finish();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
    // ARToolkitによって初期化されたcameraインスタンスから、カメラ座標系のパラメータを取得
        Size cameraSize = camera.getParameters().getPreviewSize();
        // WindowManagerから、スクリーン座標系のパラメータを取得
        Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
        // スクリーン座標系もカメラ座標系も左上隅が原点位置
        // カメラ座標系のX座標をスクリーン座標系のX座標へ変換する係数を計算

        // Edit code as Raghav Sood suggested/ 
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int height = metrics.heightPixels;
        int width = metrics.widthPixels;



        /**xRatio = (float) display.getWidth() / (float) cameraSize.width;
        // カメラ座標系のY座標をスクリーン座標系のY座標へ変換する係数を計算
        yRatio = (float) display.getHeight() / (float) cameraSize.height;
        // 非同期処理が終了したので、プログレスダイアログを消去*/

        progressDialog.dismiss();
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return gd.onTouchEvent(event);
 }

// タップ処理
private final SimpleOnGestureListener onGestureListener = new  SimpleOnGestureListener() {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        // タップされた位置をスクリーン座標系として取得
        float touchX = e.getX();
        float touchY = e.getY();
        // 認識しているすべてのマーカーの位置情報を取得
        Map<Integer, MarkerInfo> markerInfos = arToolkit.getMarkerInfos();
        for (MarkerInfo markerInfo : markerInfos.values()) {
            // カメラ座標系でのマーカー位置(マーカーの中心点)を取得
            float markerX = markerInfo.getPos()[0];
            float markerY = markerInfo.getPos()[1];

            // 認識しているマーカーの中心点をカメラ座標系からスクリーン座標系に変換し、
            // |マーカーの中心 - タップ位置| < THRESHOLD
            // であるかチェック
            if (Math.abs(markerX * xRatio - touchX) < THRESHOLD
                    && Math.abs(markerY * yRatio - touchY) <  THRESHOLD) {
                Log.d("AR_Speaker", String.format("marker %s is touched", markerInfo.getFileName()));
                for (PlayerBase player : players) {
            // すべてのPlayerに、「XXという名前のマーカーがタップされた」と通知
                    player.notifyTouch(new File(markerInfo.getFileName()).getName(), sp);
                }
            }
        }
        return true;
    }
};}

这是另一个 Activity PlayerBase:

package jp.co.tis.stc;

import java.io.BufferedReader;
import java.io.IOException;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.content.res.Resources;
import android.media.SoundPool;
import edu.dhbw.andobjviewer.graphics.Model3D;
import edu.dhbw.andobjviewer.models.Model;
import edu.dhbw.andobjviewer.parser.ObjParser;
import edu.dhbw.andobjviewer.parser.ParseException;
import edu.dhbw.andobjviewer.util.AssetsFileUtil;
import edu.dhbw.andobjviewer.util.BaseFileUtil;

public abstract class PlayerBase {
private static final double MARKER_WIDTH = 80.0;
private static final double[] MARKER_CENTER = new double[] { 0, 0 };

private final String modelFile;
private final String markerFile;
private final int voiceR;
private int soundId;
private boolean loaded = false;

protected boolean doAnimate = false;

public PlayerBase(String modelFile, String markerFile, int voiceR) {
    this.modelFile = modelFile;
    this.markerFile = markerFile;
    this.voiceR = voiceR;
}

// WaveFront形式の3Dモデルファイルを読み込み、ARToolkitが認識できる3Dモデルを構築して返す
public Model3D getModel3d(Resources resource) throws IOException, ParseException {
    BaseFileUtil fileUtil = new AssetsFileUtil(resource.getAssets());

    Model3D model3D = null;

    if (modelFile.endsWith(".obj")) {
        ObjParser parser = new ObjParser(fileUtil);
        if (fileUtil != null) {
            BufferedReader fileReader = fileUtil.getReaderFromName(modelFile);
            if (fileReader != null) {
                // Wavefront形式の3Dモデルファイルから3Dモデルを構築
                Model model = parser.parse("Model", fileReader);

                // 3Dモデルファイルとマーカーを指定して、ARToolkitへ登録するためのModel3Dオブジェクトを作成する
                model3D = new Model3D(model, markerFile, MARKER_WIDTH, MARKER_CENTER) {
                    private static final long serialVersionUID = 1L;

                    // Model3Dに仕掛けたフックの中身を定義
                    // 実際のanimate処理は、PlayerBaseを継承した具象クラスのanimateメソッドに実装することになる
                    @Override
                    protected void animate(GL10 gl) {
                        PlayerBase.this.animate(gl);
                    }
                };
            }
        }
    }
    return model3D;
}

// animate処理の抽象メソッド
protected abstract void animate(GL10 gl);

// SoundPoolへ音声をロードするメソッド
public void loadSound(Context context, SoundPool sp) {
    // res/rawに格納した音声ファイルを指定してロードすると、その音声のsoundIdが得られる
    // このメソッドは実際のロードが完成する前にリターンする
    soundId = sp.load(context, voiceR, 1);
}

// SoundPoolへの音声ロードが完成すると呼ばれるメソッド
public void notifyLoadComplete(int soundId) {
    // 自分のsoundIdのロードが完了したのならば、loadedをtrueにする
    if (this.soundId == soundId) loaded = true;
}

// マーカーがタップされた際に呼ばれるメソッド
public void notifyTouch(String fileName, SoundPool sp) {
    // 自分のマーカーがタップされたのならば、自分のsoundIdを指定して音声を再生し、doAnimateをtrueにする
    if (this.markerFile.equals(fileName) && loaded) {
        sp.play(soundId, 1.0f, 1.0f, 0, 0, 1.0f);
        if (!this.doAnimate) this.doAnimate = true;
    }
} }

最佳答案

Application is missing

这是一个 lint 错误,发生的原因是您似乎没有任何扩展 Application 的 Java 类,这在您的 list 中有所提及。您可以像以前一样忽略此错误,因为这不是应用程序的强制部分。

build.gradle error

这是一个known issue与 Android Studio。解决方法可以在this中找到。问题。

Deprecated methods

这是因为 API 13 中已弃用 getHeight()getWidth()。您可以使用 DisplayMetrics:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;

关于java - Android Studio 上 AndAR(r205) 示例代码 "nmatsui/AR_Speeker"的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22119606/

相关文章:

java - 如何使用 apache poi 获取 doc、docx 文件中特定单词的行号、页码?

java - 未触发上传进度监听器(Google Drive API)

java - 为什么我的通用方法停止工作?

java - 如何使 m2e(eclipse 的 Maven 集成)知道在哪里可以找到依赖项?

android - 更新 Android SDK 工具后 Eclipse 中的 xml 错误

Java Crowdflower API

java - 具有最大值的对象列表

java - 如何在 Java 中从另一个类获取数组

java - 如何制作按钮监听器组方法?

android - 如何从子子 Activity 转到父 Activity ?