Java Google Analytics-NetworkOnMainThread发送异步任务时出现异常
我必须在我正在开发的应用程序中实现谷歌分析。我正在使用Android Studio 我还不确定是否应该从每个活动中实现发送跟踪器,或者在Java Google Analytics-NetworkOnMainThread发送异步任务时出现异常,java,android,android-asynctask,google-analytics,android-studio,Java,Android,Android Asynctask,Google Analytics,Android Studio,我必须在我正在开发的应用程序中实现谷歌分析。我正在使用Android Studio 我还不确定是否应该从每个活动中实现发送跟踪器,或者在应用程序类中执行一次就足够了,但这是另一回事。目前,Google Analytics是在应用程序类中实现的。它试图连接到某个东西(尽管我已经设置了dryRun),但失败了,然后什么也没说,除非我导致我的应用程序崩溃。然后,当它尝试分派事件时,我得到NetworkOnMainThreadException错误 它在哪里尝试在dryRun上调度事件,导致networ
应用程序类中执行一次就足够了,但这是另一回事。目前,Google Analytics是在应用程序类中实现的。它试图连接到某个东西(尽管我已经设置了dryRun
),但失败了,然后什么也没说,除非我导致我的应用程序崩溃。然后,当它尝试分派事件时,我得到NetworkOnMainThreadException
错误
它在哪里尝试在dryRun
上调度事件,导致networkonmainthreadeception
同样严重?它不应该在运行dryRun
时将所有内容分派到Logcat中吗?我应该如何在dryRun
和not上处理它
起初,我尝试像那样实现它,没有额外的AsyncTask
类,假设我将把所有内容都转储到Logcat,但是当我第一次遇到networkMainThreadException
错误时,我实现了AsyncTask
类
日志:
01-15 13:06:21.835 1787-1800/com.example.app W/GAV4﹕ Thread[GAThread,5,main]: Service unavailable (code=1), will retry.
01-15 13:06:26.847 1787-1808/com.example.app W/GAV4﹕ Thread[Service Reconnect,5,main]: Service unavailable (code=1), using local store.
01-15 13:07:12.695 1787-1787/com.example.app E/GAV4﹕ Thread[main,5,main]: Error dispatching all events on exit, giving up: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:926)
at org.apache.http.impl.SocketHttpClientConnection.shutdown(SocketHttpClientConnection.java:183)
at org.apache.http.impl.conn.DefaultClientConnection.shutdown(DefaultClientConnection.java:150)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.shutdown(AbstractPooledConnAdapter.java:169)
at org.apache.http.impl.conn.AbstractClientConnAdapter.abortConnection(AbstractClientConnAdapter.java:378)
at org.apache.http.impl.client.DefaultRequestDirector.abortConnection(DefaultRequestDirector.java:1031)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:530)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:509)
at com.google.android.gms.analytics.h.a(Unknown Source)
at com.google.android.gms.analytics.h.a(Unknown Source)
at com.google.android.gms.analytics.ag.dispatch(Unknown Source)
at com.google.android.gms.analytics.w.eD(Unknown Source)
at com.google.android.gms.analytics.w.dispatch(Unknown Source)
at com.google.android.gms.analytics.x$b.run(Unknown Source)
at com.google.android.gms.analytics.x.dY(Unknown Source)
at com.google.android.gms.analytics.GoogleAnalytics.dY(Unknown Source)
at com.google.android.gms.analytics.ExceptionReporter.uncaughtException(Unknown Source)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
at dalvik.system.NativeStart.main(Native Method)
应用类别(相关部分):
SendTrackeringbg:
public class SendTrackerInBg extends AsyncTask<Tracker, Void, Integer> {
SendTrackerInBg(Tracker t)
{
this.execute(t);
}
@Override
protected Integer doInBackground(Tracker... trackers) {
try {
trackers[0].send(new HitBuilders.AppViewBuilder().build());
return 0;
}
catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
公共类SendTrackerInBg扩展异步任务{
发送跟踪器BG(跟踪器t)
{
这个。执行(t);
}
@凌驾
受保护的整数doInBackground(跟踪器…跟踪器){
试一试{
跟踪器[0]。发送(新建HitBuilder.AppViewBuilder().build());
返回0;
}
捕获(例外e){
e、 printStackTrace();
返回-1;
}
}
}
app_tracker.xml(相关部分):
300
真的
应用
300
UA-xxxxxxxx-1
真的
analytics_global_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="ga_dryRun">true</bool>
<string name="ga_logLevel">verbose</string>
</resources>
真的
冗长的
舱单(相关部分):
UPD:多亏了@Bart Hofma,我意识到我的应用程序崩溃可能让人困惑。GA试图调度事件时,我的应用程序不会崩溃。相反,GA试图仅在我的应用程序崩溃时发送事件,否则它将保持沉默。我故意破坏我的应用程序,看看GA会说些什么。我有一个自定义视频播放器,在真实设备上运行良好,但在虚拟机上崩溃,所以当我想让我的应用程序崩溃时,我只需转到虚拟机上的播放器活动。你必须从线程调用google analytics。在这里,我将分享我正在使用的代码
将此代码放入类(MBGoogleAnalyticsManager.java)中
现在,您必须调用该类实例、方法并提供调用该类所需的数据,如下所示:
private void sendScreenView(final String screenName)
{
new Thread(new Runnable()
{
@Override
public void run()
{
analyticsManager = MBGoogleAnalyticsManager.getInstance(getApplicationContext());
analyticsManager.sendGoogleAnalyticsSreenView(screenName);
}
}).start();
}
并将此方法称为:
sendScreenView(“家庭活动”)
希望你会发现它有帮助。我浪费了一天时间搜索解决方案(我有相同的线程转储行),并发布了与Google Analytics没有直接关系的消息。根本原因是下一行:adView.destroy();其中adView==null。Google Analytics似乎试图发送此异常并自行崩溃。
我完全是通过禁用Google Analytics找到的。我不知道什么是dryrun,但看起来你只是在你的主课上建立网络连接。因此,我猜您忘了从那里移动一些代码,或者实现了错误的异步任务。虽然您的问题不包括Main的代码,但也没有在清单中指定(删除它以提高可读性?)我认为您应该在question@BartHofma SDK提供了一个dryRun标志,当设置该标志时,将阻止任何数据发送到Google Analytics。只要您正在测试或调试一个实现,并且不希望测试数据出现在您的Google Analytics报告中,就应该设置dryRun标志。“我在MainActivity中未建立任何网络连接。我甚至还没有开始在那里实施谷歌分析,当我犯了第一个错误时,我就从StartActivity中删除了所有关于GA的内容--@BartHofma--我没有包括整个清单,因为我有12个活动和大约同样多的片段,我想这些会把帖子弄得乱七八糟。不过还是要谢谢你的意见。我可以添加我的StartActivity(删除URL、令牌等),但那是333行无关代码。请任何人解释一下投票失败的原因好吗?你完全正确,只是遇到了同样的问题,是的,它似乎是由带有未捕获异常的干运行标志引起的-在我的例子中,在ExceptionReporter.uncaughtException之后,我有我自己的布局异常。幸运的是,当不是干运行时,问题不会发生,所以祈祷生产运行成功。不确定问题需要报告的确切位置,可能在这里:或者请在这里发布问题。如果您正在设置GA帐户,它最多可能需要48小时才能工作,您将在第二天获得特定一天的数据。对我来说也是如此,但我没有禁用分析,而是在其块上使用了try/catch。是的,我的意思是要找到有问题的块,我必须禁用Google Analytics捕获异常。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="ga_dryRun">true</bool>
<string name="ga_logLevel">verbose</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:versionCode="00"
android:versionName="0.00" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<permission
android:name="com.example.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.app.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<meta-data
android:name="com.google.android.gms.analytics.globalConfigResource"
android:resource="@xml/analytics_global_config" />
<application
android:name=".App"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
import android.content.Context;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
public class MBGoogleAnalyticsManager
{
private static final String TAG = "MBGoogleAnalyticsManager";
private static MBGoogleAnalyticsManager instance = null;
public String PROPERTY_ID = "UA-28454545-2";
private Context context;
private Tracker dataTracker;
public static MBGoogleAnalyticsManager getInstance(Context c)
{
if(instance == null)
{
System.out.println("MBGoogleAnalyticsManager new instance is created");
instance = new MBGoogleAnalyticsManager(c);
}
else
{
System.out.println("MBGoogleAnalyticsManager instance is already avaiable");
}
return instance;
}
private MBGoogleAnalyticsManager(Context c)
{
//super(c);
context = c;
GoogleAnalytics analytics = GoogleAnalytics.getInstance(context);
dataTracker = analytics.newTracker(PROPERTY_ID);
}
//==============================================================================
//========================== Send a screen view =================================
//================================================================================
public synchronized void sendGoogleAnalyticsSreenView(String screenName)
{
dataTracker.setScreenName(screenName); // Set screen name.
//dataTracker.setAppName("MovieBuddy"); // We can send the application name [String](Optional)
//dataTracker.setAppVersion("2.2"); // We can send the application version [String](Optional)
//dataTracker.setLanguage("Eng"); // We can send the language [String](Optional)
//dataTracker.setSessionTimeout(300); // We can set the time for the session time out [Long](Optional)
dataTracker.send(new HitBuilders.AppViewBuilder()
//.setNewSession() // If want to start a new session (Optional)
.build());
System.out.println("Screen: "+screenName);
}
//==============================================================================
//========================== Send A Click Event Hit =============================
//================================================================================
public synchronized void sendGoogleAnalyticsHitEvents(String screenName,String category,String action,String label)
{
dataTracker.setScreenName(screenName);
dataTracker.send(new HitBuilders.EventBuilder()
.setCategory(category) // Set the category of the event [String]
.setAction(action) // Set the action has taken for the event [String]
.setLabel(label) // Set the label of for the event [String]
.build());
System.out.println("Hit Label: "+label);
}
//==============================================================================
//========================== Send A Exception Event =============================
//================================================================================
public synchronized void sendGoogleAnalyticsException(String screenName,String ExceptionMethodName,String ExceptionLocation,boolean ExceptionFatal)
{
dataTracker.setScreenName(screenName);
dataTracker.send(new HitBuilders.ExceptionBuilder()
.setDescription(ExceptionMethodName + ":" + ExceptionLocation) // Send the exception details [String]
//(Never send the e.message, as it contains personal info)
.setFatal(ExceptionFatal) // Send true or false if fatal exception error [boolean]
.build());
}
//==============================================================================
//================ Send A Social Event Interaction With target ==================
//================================================================================
public synchronized void sendGoogleAnalyticsSocialInteractionWithTarget(String screenName,String SocialNetworkName,String SocialAction,String SocialTarget)
{
dataTracker.setScreenName(screenName);
dataTracker.send(new HitBuilders.SocialBuilder()
.setNetwork(SocialNetworkName) // Set the Social Network Name [String]
.setAction(SocialAction) // Set the action [String]
.setTarget(SocialTarget) // Set the target [String](Not a mandatory field)
.build());
System.out.println("Target: "+SocialTarget);
}
//==============================================================================
//============== Send A Social Event Interaction Without target =================
//================================================================================
public synchronized void sendGoogleAnalyticsSocialInteraction(String SocialNetworkName,String SocialAction)
{
dataTracker.send(new HitBuilders.SocialBuilder()
.setNetwork(SocialNetworkName)// Set the Social Network Name [String]
.setAction(SocialAction) // Set the action [String]
.build());
}
}
private void sendScreenView(final String screenName)
{
new Thread(new Runnable()
{
@Override
public void run()
{
analyticsManager = MBGoogleAnalyticsManager.getInstance(getApplicationContext());
analyticsManager.sendGoogleAnalyticsSreenView(screenName);
}
}).start();
}