마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

jar파일 내부의 service 관련

0 추천

안녕하세요

현재 게임엔진에서 안드로이드 프로젝트의 jar파일을 

라이브러리 형태로 불러와 해당 jar파일 내부에 잇는

service 클래스를 startService() 하고 

해당 service는 onCreate 되자마자

googleApiclient.build()를 실행하고

 

onConnected() 가 호출 되자마자 

같이 페어링된 Wear 에 sendMessage를 보냅니다. ( 테스트를 위해 연결되자마자 메시지를 하나 보내게 

해놓음)

 

이때 onconnected()  호출 될시의 보낸 sendmessage는 정상적으로 보내지고

해당 wear에서도 메시지를 받고 로그가 찍히는대 

 

이상하게 실제 엔진에서 원하는 부분에서 좀전에 생성한 service 클래스로 함수를 호출하고

Sendmessage를 보낼라고 하면 oncreate에서 생성한 googleapiclient가 Null이 되어서 

자꾸 터지네요... 

 

물론 service 가 꺼지면 로그가 찍히게 onDestroy 에 로그를 찍어 놓았는대 해당 로그는 찍힌적이 없고요

 

 

아래 코드가 service 클래스의 코드부분입니다 

public class WatchService extends Service implements
        MessageApi.MessageListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        NodeApi.NodeListener,
        DataApi.DataListener

{

    GoogleApiClient googleClient;

    private static final String TAG = "[MyLog_WatchService]";
    private static final String START_ACTIVITY_PATH = "/wearable_data";

    public final int STATE_WAITTING = 0;
    public final int STATE_BATTLE_ING = 1;
    public final int STATE_BATTLE_CLEAR = 2;
    public final int STATE_BATTLE_FAIL = 3;
    public final int STATE_NOT_ENOUGH_KEY = 4;

    public final String EVENT_RETRY = "requst_retry";
    public final String EVENT_NEXT = "request_next_dungeon_enter";
    public final String EVENT_BEFORE = "request_before_dungeon_enter";

    public ArrayList<String> eventdata = new ArrayList<String>();

    @Override
    public void onCreate() {
        Log.v(TAG, "WatchService ServiceCall onCreate");
        super.onCreate();
        googleClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        //OnWakeUp_Wear();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.v(TAG, "WatchService ServiceCall onStartCommand" );
        googleClient.connect();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onConnected(Bundle bundle)
    {
        Log.v(TAG, "WatchService onConnected");
        Wearable.DataApi.addListener(googleClient, this);
        Wearable.MessageApi.addListener(googleClient, this);
        Wearable.NodeApi.addListener(googleClient, this);
        sendDataLayerMessage("Onconnected Test Msg");
        

    }

 

 

그리고 엔진 부분에서 호출되는 함수입니다 같은 service 클래스 내부에 존재합니다

public void SendToAndorid_Waitting(int state)
{
    Log.v(TAG, "WatchService SendToAndroid_Waitting_From_Unreal:" + state);
    DataMap data = new DataMap();
    data.putInt("state", state);
    if( googleClient == null)
    {
        Log.v(TAG, "GoogleClient Null...");
        Log.v(TAG, "GoogleClient Re Build...");
        googleClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        Log.v(TAG, "GoogleClient Re Connect Try");
        googleClient.connect();
        eventdata.add("Waiting");
    }
    else
    {
        Log.v(TAG, "GoogleClient Connect Check");
        if(!googleClient.isConnected()  || !googleClient.isConnecting())
        {
            Log.v(TAG, "Connected Break");
            Log.v(TAG, "Reconnect Try");
            googleClient.connect();
            eventdata.add("Waiting");
        }
    }

    sendDataLayerMessage("Waiting");
    //new SendToDataLayerThread(START_ACTIVITY_PATH, data ).start();
}

 

제가 에러가 나는 부분을 간단히 다시 정리하면

1> 게임 프로젝트가 실행되며  startservice()로 jar파일내의 service class 호출 

2> service class onCreate()호출시 googleapiclient.build() 를 실행 

3> service class onstartcommand() 호출시 googleapilcinet.connect() 실행

4> service class onconnected() 호출 테스트로 sendmessage() 실행

5> 해당 메시지에 대한 로그도 잘찍히며 페어링된 wear에서도 메시지를 받은 로그 확인

6> 실제 직접사용할 엔진에서 안드로이드로 함수 호출(JNI 이용) 

7> 호출된 안드로이드 함수 호출 로그 확인 sendmessage

 

아래 로그 출력

 

11-04 11:12:30.646: V/[MyLog_WatchService](605): WatchService SendToAndroid_Waitting_From_Unreal:0
11-04 11:12:30.646: V/[MyLog_WatchService](605): GoogleClient Null...
11-04 11:12:30.646: V/[MyLog_WatchService](605): GoogleClient Re Build...
11-04 11:12:30.647: W/System.err(605): java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference
11-04 11:12:30.647: W/System.err(605):     at android.content.ContextWrapper.getMainLooper(ContextWrapper.java:102)
11-04 11:12:30.647: W/System.err(605):     at com.google.android.gms.common.api.GoogleApiClient$Builder.<init>(Unknown Source)
11-04 11:12:30.647: W/System.err(605):     at com.example.g9kim.wearproject.WatchService.SendToAndorid_Waitting(WatchService.java:283)

 

service 라는게 원래 이렇게 생성한 객체가 일정시간이 지나면 날라가 버리나요,,?

 

아니면 jar파일 내부에 잇는 service 라서 그런건가요? 

 

이해가 잘안되네요 왜 이런건지 

 

도움 부탁드려요~

 

 

하루일과 (330 포인트) 님이 2015년 11월 4일 질문

1개의 답변

0 추천
SendToAndorid_Waitting 호출 시점에 Service가 제대로 초기화되어있지 않은 것으로 보입니다.

해당 메소드를 어떤식으로 호출하나요?
익명사용자 님이 2015년 11월 4일 답변
해당 함수는 엔진에서 JNI를 통해서 호출되요

저도 정확한 과정은 모르고요 샘플코드 보고 따라한 정도여서요
java code 내에는 해당함수 호출부분이 없고

엔진의 c++ 코드 내에 잇어요

제대로 초기화가 안된다면...

startservice를 엔진의 java code에서 jar 파일안의 service 클래스를 실행시키는 방식인데 그래서 그런건가요?
SendToAndorid_Waitting를 직접 호출하려면 해당 서비스에 bind 하는 과정을 거쳐야 합니다.
위의 코드를 봐서는 그런식으로 사용하는 것 같지 않군요.
원인이 해결되었어요 ㅜㅜ Service 클래스가 두개 생성 된거였엇어요
엔진쪽 java code 에서 생성한 Service 클래스 A( 해당 클래스에선 googleapiclient 연결이 됨) 엔진쪽 c++ 코드에서 안드로이드로 호출시 생성된 service 클래스B (여기선 googleapiclient가 연결이안됨)

때분에 service 클래스 B 에선 메시지 전송이 안되고 잇엇어요

그래서 게임엔진과 서로 메시지 전송을 수행할 Bridge 클래스를 만들어서
엔진과 안드로이드 통신을 하고
Service 클래스는 생성될때 static 으로 자기자신을 객체로 만들어 놓고
Bridge에서 메시지가 발생햇을때 Service 클래스의 static 객체를 이용해서
Service 클래스의 함수를 호출 하여 wear app 과 통신을 주고 받는식으로 했습니다

답변 주셔서 감사해요^^
이 댓글을 보실지는 모르겠으나 Context를 상속받은 클래스를 static 변수에 저장하면 오류가 발생할 수 있습니다. 구조를 바꾸시기 바랍니다.
...