【问题标题】:App crashes when I return to map activity containing ad banner?当我返回包含广告横幅的地图活动时应用程序崩溃?
【发布时间】:2020-12-10 18:43:27
【问题描述】:

每当我返回 (onResume) 到我唯一的活动时,我的应用程序就会崩溃并出现以下错误。我的活动仅包含 Google 地图和横幅广告(来自 Facebook Audience Network)

A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 14320 (RenderThread), pid 14265

我该如何解决这个问题?我会很感激你在这方面的帮助。我的代码很简单,找不到问题。

这是我的activity_maps.xml

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraintLayout"
    tools:context=".MapsActivity">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MapsActivity" />

    <LinearLayout
        android:id="@+id/banner_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

这是我的MapsActivity.java

import androidx.fragment.app.FragmentActivity;

import android.os.Bundle;
import android.widget.LinearLayout;
import com.facebook.ads.AdSize;
import com.facebook.ads.AdView;
import com.facebook.ads.AudienceNetworkAds;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private AdView adView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        AudienceNetworkAds.initialize(this);

        adView = new AdView(this, "my_placement_id", AdSize.BANNER_HEIGHT_50);

        // Find the Ad Container
        LinearLayout adContainer = findViewById(R.id.banner_container);

        // Add the ad view to your activity layout
        adContainer.addView(adView);

        // Request an ad
        adView.loadAd();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
    }
}

它是这样的:

【问题讨论】:

  • simplifiedcoding.net/… 是否回答了您的问题?
  • 你能分享一下错误信息的细节吗?此类 DEBUG 信息,如 this questionUPDATE 段落,通常包含找出本地库中发生崩溃的位置的线索。
  • 附带说明,您似乎将广告横幅置于 Google Maps Platform 属性(徽标、版权等)之上。请注意,这可能违反了 Google 地图服务条款,尤其是第 3.2.2 (b) 项中的归属:cloud.google.com/maps-platform/terms/#3.-license

标签: java android google-maps kotlin facebook-audience-network


【解决方案1】:

Logcat message

A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 14320 (RenderThread), pid 14265
  • A/libc 表示优先级为A(Assert),标签为libcbionic)。
  • 消息是Fatal signal 11 (SIGSEGV),这意味着您的应用程序自行终止,收到segmentation violation 的信号。
  • code 1 (SEGV_MAPERR), fault addr 0x0 详细说明 libc 无法读取或写入内存地址 0x0(空指针),如 this answer 中所述。
  • 其余的in tid 14320 (RenderThread), pid 14265 表明此崩溃发生在进程14265 的线程14320 (RenderThread) 中。

RenderThread 表示这可能是由于hardware acceleration

要关闭加速,添加一个属性

android:hardwareAccelerated="false"

AndroidManifest.xml 中的这些元素之一。

我觉得值得一试。

【讨论】:

  • 为什么加速会导致这个问题?在示例记录中,他没有翻转手机。
【解决方案2】:

正如 qtmfld 所指出的,您的错误很可能发生在 RenderThread 中。我有根据的猜测是,这与您在地图片段顶部绘制的横幅广告有关。

在 xml 布局中使用硬编码的片段元素时存在已知的绘图问题,尤其是在使用片段事务时。因此,SupportFragmentManager 可能会在重新创建片段状态时以某种方式试图覆盖横幅广告,从而导致崩溃。

除此之外,Google's ad policies 禁止在用户与之交互的组件上方使用横幅广告。

要确认这一点,您可以尝试更改布局约束,使横幅广告不会覆盖地图片段:

 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toTopOf="@id/banner_container"
    tools:context=".MapsActivity" />

【讨论】:

  • 是的,这违反了 Google 广告政策,但这不会导致任何错误。也许是一个警告。但这绝对是一个很好的提示,请注意这些政策。
【解决方案3】:

你搞混了一些东西!

查看以下 Facebook 文档:initialize-the-audience-network-sdk

您可以看到他们在 Application 类中而不是在 Activity 中调用 AudienceNetworkAds.initialize(this);

在文档中创建一个类:

public class YourApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // Initialize the Audience Network SDK
        AudienceNetworkAds.initialize(this);       
    }

}

下一步是在 Manifest 文件中添加带有android:name=".YourApplication" 的类,如示例中所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.rieger.com.myapplication">
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:name=".YourApplication"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

这告诉 Android 在哪里可以找到您的 Application 类的实现。

然后从 MapsActivity 类的 onCreate() 方法中删除 AudienceNetworkAds.initialize(this); 行。

现在一切都应该正常了。

为什么会出现异常?

查看活动生命周期。

系统可以在每次启动 Activity 时调用 onCreate(),而不仅仅是 onResume() 或 onStart()。

发生的情况是,当您第二次通过 onCreate() 方法打开 Activity 时,模拟器会调用 onCreate()。这会导致第二次调用 AudienceNetworkAds.initialize(this); 导致错误。

另一个提示

不要忘记实现 onDestroy() 方法,例如:

@Override
protected void onDestroy() {
    if (adView != null) {
        adView.destroy();
    }
    super.onDestroy();
}

【讨论】:

  • 除了没有必要并且会导致开销之外,多次初始化有什么问题?内存泄漏?
  • @nulldroid 如您在developers.facebook.com/docs/audience-network/reference/android/… 下阅读的那样,您应该尽快初始化SDK。是的,您可以在 Activity 的 onCreate() 方法中调用 initialize(),但前提是您确实想在一个 Activity 中使用它。但是,您必须首先检查 SDK 是否已经使用 isInitialized() 进行了初始化。那么,当您可以在应用程序启动时初始化 SDK 时,为什么还要在每个带有广告的 Activity 中检查和初始化呢?
【解决方案4】:

请检查您是否使用基于HAXM 的模拟器,并检查它是否也发生在真实设备中。

你也可以试试Google Maps Android SDK v.3.1.0 BETA,看看bug是否还存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 2018-11-26
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多