gpt4 book ai didi

android - 为什么调用外部 java 函数会导致我的应用程序崩溃? (亚马逊社交网络、S3)

转载 作者:行者123 更新时间:2023-11-29 00:05:59 26 4
gpt4 key购买 nike

我们正在整合一个使用 Amazon S3 和 SNS SDK 的 Unity 应用程序。他们自己工作得很好——只有 SNS,应用程序才能正确注册和接收通知,使用 S3,我们可以很好地下载图像和视频。

将 SDK 组合到一个应用程序现在会导致问题,几个小时后我找到了导致崩溃的行:

GCM.cs

string regId = cls.CallStatic<string>("register",senderIds);

奇怪的是,此时 ADB logcat 没有给出任何错误,但在此调用之后返回之前,然后才知道这是应用程序崩溃的地方。奇怪的是,推送注册过程在 ADB 中继续进行,同时显示“此应用程序已崩溃”消息,直到它成功完成,就像应用程序正常启动一样......

正在调用的“注册”函数在 AWSUnityGCMWrapper.java

public static String register(final String senderIds) {
try {
if (senderIds == null) {
return "";
}
Activity activity = UnityPlayer.currentActivity;
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(activity);
String regId = gcm.register(senderIds);
storeRegistrationId(activity, regId);
return regId;
} catch (IOException e) {
Log.e(TAG, "failed to register the to gcm");
Log.e(TAG, "exception = " + e.getMessage());
}
return "";
}

尝试了 AndroidManifest.xml 的许多配置但没有成功,除了通过 logcat 似乎一切正常! CallStatic 正确返回并且该过程继续进行,直到在崩溃弹出窗口上按下“确定”...

知道为什么这个调用静态函数会导致这个问题吗?如果需要,请索取更多代码示例!

编辑:AndroidManifest.xml 如果有帮助...

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company.appname"
android:installLocation="preferExternal"
android:theme="@android:style/Theme.NoTitleBar"
android:versionCode="1"
android:versionName="1.0">

<uses-feature android:name="android.hardware.camera" />

<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- PUSH --><uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!-- PUSH --><permission android:name="com.company.appname.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<!-- PUSH --><uses-permission android:name="com.company.appname.permission.C2D_MESSAGE" />

<application
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:debuggable="false">
<activity android:name="com.unity3d.player.UnityPlayerNativeActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>

<activity android:name="com.unity3d.player.VideoPlayer"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
</activity>

<!-- PUSH --><receiver
android:name="com.company.appname.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.company.appname" />
</intent-filter>
</receiver>

<!-- PUSH --><service android:name="com.company.appname.GCMIntentService" />

<!--
To support devices using the TI S3D library for stereo mode we must
add the following library.
Devices that require this are: ODG X6
-->
<uses-library android:name="com.ti.s3d" android:required="false" />
<!--
To support the ODG R7 in stereo mode we must add the following library.
-->
<uses-library android:name="com.osterhoutgroup.api.ext" android:required="false" />
</application>

编辑 - AWSUnityGCMWrapper.java 使用 AsyncTask

public static String register(final String senderIds) {

// Async Task
_regID = "0";
_done = false;

new RegTask().execute(senderIds);

while(!_done);

return _regID;

}

public static void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGCMPreferences(context);
int appVersion = getAppVersion(context);
Log.i(TAG, "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
editor.commit();
}

public static void setReg(String regID) {
_done = true;
_regID = regID;
}

public static String getReg() {
return _regID;
}

private static class RegTask extends AsyncTask<String, Void, String> {

String _regID;

public RegTask() {
super();
_regID = "0";
}

@Override
protected String doInBackground(String... params) {

Log.i(TAG, ">>> Registering With GCM Async Task... Sender: " + params[0]);
String senderIds = params[0];
try {
if (senderIds == null) {
//_regID = "0";
return "0";
}
Log.i(TAG, ">>> Trying Registration...");
Activity activity = UnityPlayer.currentActivity;
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(activity);
String regId = gcm.register(senderIds);
Log.i(TAG, ">>> New Registration ID: " + regId);
storeRegistrationId(activity, regId);
//_regID = regId;
return regId;
} catch (IOException e) {
Log.e(TAG, "failed to register the to gcm");
Log.e(TAG, "exception = " + e.getMessage());
}

//_regID = "0";
Log.i(TAG, ">>> Registering With GCM Async Task Done...");
return "0";
}

@Override
protected void onPostExecute(String result) {
setReg(result);
}
}

在 Logcat 中

I/AWSUnityGCMWrapper(21896):>>> 正在注册 GCM 异步任务...发件人:750882817708I/AWSUnityGCMWrapper(23338):>>> 新注册 ID:APA91bHWev8CCsbso8JE5a28J...I/AWSUnityGCMWrapper(21896):在应用程序版本 1 上保存 regId

当按下注册按钮时,应用程序仍然立即崩溃。

最佳答案

因此,根据我们在您帖子下的评论中的讨论,您注册 GCM 的代码应该在 UI 线程中运行。也就是说,您应该将您的函数包装在一个 runOnUiThread() 中,这是您通过以下方式完成的:

  1. 创建一个 Runnable 类MyRunnable r = new MyRunnable(UnityPlayer.currentActivity, senderIds);

  2. 像这样运行它:UnityPlayer.currentActivity.runOnUiThread(r);

它所做的不再是崩溃,而是抛出异常(在您的日志中称为 MAIN_THREAD)。

你应该做的不仅仅是在你的可运行函数中调用 .register(...) 在后台调用它,例如在 AsyncTask 中:

private void registerBackground(final String senderId) {
new AsyncTask() {
@Override
protected String doInBackground(Void... params) {
String msg = "";
try {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(UnityPlayer.currentActivity);


String regId = gcm.register(senderId);
storeRegistrationId(UnityPlayer.currentActivity, regId);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}

@Override
protected void onPostExecute(String msg) {
// msg returned
}
}.execute(null, null, null);

这是因为Android上的UI操作发生在主线程上,而网络必须在后台完成。

调用它而不是您的注册函数,如果有帮助请告诉我。

编辑:

顺便说一句,您可能想要监听更改或以适当的方式等待它们,因为我可以看到您的静态 f-tion 返回字符串。

编辑2:

因此,在我的建议下,您已将其移至适当的异步任务。但是还有一个等待结果的问题。要做到这一点,你可以写这样的东西而不是一会儿:

Handler myHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
_done = true;
break;
default:
break;
}
}
};

也在你的任务的 onPostExecute() 中调用这个 myHandler.sendEmptyMessage(0);

然后,在您的函数中创建一个可运行的或另一个简单的服务员,而不是 while() 。但是现在,您可能想使用 Thread.sleep(1000) 对其进行测试;一段时间内以减轻 UI 上的负载。

关于android - 为什么调用外部 java 函数会导致我的应用程序崩溃? (亚马逊社交网络、S3),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33762218/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com