I have a little app that I made that have worked for months, but suddenly I get a
android.os.NetworkOnMainThreadException
I havent changed any code, this is the line that crashes
try {
endPoint = InetAddress.getByName(target.getToIp());
port = target.getPort();
socket = new DatagramSocket();
}
catch(Exception e) {
}
Note that I'm not sending anything I'm just creating the instances, it breaks already on the InetAddress row.
It wored as late as last night, all I have done on the phone is run update on Google play, it updated to latest version of Google Maps, but that cant have anything todo with it?
It works in the emulator, only my HTC One X that breaks
Full code here
https://github.com/AndersMalmgren/FreePIE/tree/master/Lib/Android/FreePIE%20Android%20IMU
edit:
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.freepie.android.imu"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Tried to move the problem code to the thread instead, now it wont break, but the socket is set to null.
running = true;
worker = new Thread(new Runnable() {
public void run(){
try {
endPoint = InetAddress.getByName(target.getToIp());
port = target.getPort();
socket = new DatagramSocket();
}
catch(Exception e) {
Exception err = e;
}
while(running) {
try {
sync.await();
} catch(Exception e) {}
Send();
}
try {
socket.disconnect();
}
catch(Exception e) {}
}
});
worker.start();
update:
Solution was to add some failback if user types a DNS instead of a IP
https://github.com/AndersMalmgren/FreePIE/commit/e8017e02a7893d9df41e4ed67a037f016b6a7d39
You will get NetworkOnMainThreadException on Android 4.0+ by default if you attempt to do network I/O on the main application thread. getByName() does a DNS lookup if you provide a domain name (instead of dotted-IP notation), and that will trigger NetworkOnMainThreadException.
You must put your code in AsyncTask like this:
new AsyncTask<Void,Void,Void>(){
doInBackground(){
endPoint = InetAddress.getByName(target.getToIp());
port = target.getPort();
socket = new DatagramSocket();
}
}.execute();
Note this code is not a working one, please read more about AsyncTasks here
Use Network on main thread is not allowed from the Android 4.0. If you run the code at Android 2.3 or other, it will not throw any exception.
Related
Android Studio 2.3.3 (LATEST)
Cocos2d-x 3.15.1 (LATEST)
I tested on Debug.
It's my first experience with Cocos2d-x Game Engine, I developed an Android Game using Cocos2d-x, all it's fine but when I tried to show the achievements it shows me an error like this :
java.lang.NullPointerException
at sonar.systems.framework.SonarFrameworkFunctions.showAchievements(SonarFrameworkFunctions.java:432)
at org.cocos2dx.lib.Cocos2dxRenderer.nativeTouchesEnd(Native Method)
at org.cocos2dx.lib.Cocos2dxRenderer.handleActionUp(Cocos2dxRenderer.java:129)
at org.cocos2dx.lib.Cocos2dxGLSurfaceView$10.run(Cocos2dxGLSurfaceView.java:311)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1486)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1263)
My Code when I click to show the achievements :
SonarCocosHelper::GooglePlayServices::showAchievements();
When I want To sign In :
java.lang.NullPointerException
at sonar.systems.framework.SonarFrameworkFunctions.isSignedIn(SonarFrameworkFunctions.java:277)
at org.cocos2dx.lib.Cocos2dxRenderer.nativeRender(Native Method)
at org.cocos2dx.lib.Cocos2dxRenderer.onDrawFrame(Cocos2dxRenderer.java:105)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1557)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1263)
My Code for Sign In :
if(!SonarCocosHelper::GooglePlayServices::isSignedIn())
SonarCocosHelper::GooglePlayServices::signIn();
My Manifest File :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ilyo.test"
android:installLocation="auto">
<supports-screens android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-feature android:glEsVersion="0x00020000" />
<!-- Basic permission for Internet and don't allow turn of the screen -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:label="#string/app_name"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#mipmap/ic_launcher">
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="MyGame" />
<!-- Required for Google Play Services -->
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="#string/app_id" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<activity
android:name="org.cocos2dx.cpp.AppActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Build Gradle File :
Cocos Helper Frameworks Used :
My Google Play Achievement (I removed the ID from this photo):
I searched already for solutions in relationship with Android Studio but the results are very rare, I don't know what is the solution and what this the reason for this error.
Thank you,
I founded a solution but now I guess it's just a dirty fix, first the problem is in the GooglePlayServices.java and exactly in onStart method : Null pointer Exception because mHelper is Null.
#Override
public void onStart()
{
mHelper.onStart((Activity) ctx);
}
Let us a little further why it generates null, so :
1. SonarFrameworkFunctions.java
when we want to call GooglePlayServices constructor from SonarFrameworkFunctions.java :
//GOOGLE PLAY SERVICES
if (SonarFrameworkSettings.USE_GOOGLE_PLAY_GAME_SERVICES)
{
String packageName = "sonar.systems.frameworks.GooglePlayServices.GooglePlayServices";
googlePlayServices = (InstantiateFramework(packageName) != null) ? InstantiateFramework(packageName) : new Framework();
}
2. Method : InstantiateFramework in SonarFrameworkFunctions.java
public static Framework InstantiateFramework(String packageName)
{
Framework tmp = null;
try
{
tmp = (Framework) Class.forName(packageName).getConstructor().newInstance();
tmp.SetActivity(((SonarFrameworkActivity) app));
} catch (InstantiationException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
Log.e("Class not found", "class doesn't exist or bad package name " + packageName);
}
return tmp;
}
The constructor is empty so there is only a method called onCreate that instantiate and prepare the mHelper to access to all functionalities of Google Play Services.
Solution (Dirty Fix):
GooglePlayServices.java
public GooglePlayServices()
{
mHelper=getGameHelper();
mHelper.setup(this);
}
I'm writing an acessibility service in Android which relies on getting the view id of the currently selected view, however on some devices (Nexus 6P 6.0.1, Samsung Galaxy S6 edge+ 5 + 6.0.1) I get no view id through and on others (HTC One M8 5.0.1) it comes through fine. Because it works fine on some devices, I'm sure there's not a problem with my code, however I've posted a minimal test case below.
Can anyone can help me get my service reporting ids across all devices?
The A11y service
public class ViewIdLoggingAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source == null) {
Log.d("onAccessibilityEvent", "source was null for: " + event);
} else {
String viewIdResourceName = source.getViewIdResourceName();
Log.d("onAccessibilityEvent", "viewid: " + viewIdResourceName);
}
}
#Override
public void onInterrupt() {
Log.d("!# onInterrupt", "called");
}
}
The AndroidManifest.xml
<manifest package="com.example.a11yservice"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
>
<service
android:name=".ViewIdLoggingAccessibilityService"
android:label="#string/view_id_logging_service_label"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
>
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/serviceconfig"
/>
</service>
</application>
</manifest>
serviceconfig.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100" />
It's known issue and was posted to AOSP issue tracker some time ago. You can check status of issue here: "Accessibility Issue: flagReportViewIds has no effect on real devices in Android M".
Unfortunately issue exists even on latest Android 7.0 but I found simple workaround. You can call refresh() method on AccessibilityNodeInfo object to refresh it and collect all missed data including id.
Something like that:
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo ani = event.getSource();
if (ani != null) {
ani.refresh(); // to fix issue with viewIdResName = null on Android 6+
}
}
I found that if the viewId isn't available, querying the focused element seems to work:
AccessibilityNodeInfo source = findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
viewIdResourceName = source.getViewIdResourceName();
returns the correct view id
I am trying to write an Android app that uses com.loopj.android.http.AsyncHttpClient. Although I wrote an Android app some years ago, I am very rusty, so please be gentle with me!
In my app, I do a get, and none of the callback virtual methods are called. To simplify, and make sure it wasn't something about my app, I made a new project based on the SupportAppNavigation project that comes with the SDK. I modified the onCreate code as follows:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("com.trumphurst", "Creating AsyncHttpClient");
AsyncHttpClient client = new AsyncHttpClient();
client.setTimeout(5000);
Log.i("com.trumphurst", "Getting www.google.com");
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
Log.i("com.trumphurst", "Success");
}
#Override
public void onFailure(Throwable error, String content) {
Log.i("com.trumphurst", "Failure");
}
});
setListAdapter(new SampleAdapter(querySampleActivities()));
}
(Note that this is the only code change I have made to the example application that comes with the SDK.)
I started the app under the debugger, and monitored the logcat output. I saw "Creating AsyncHttpClient" and "Getting www.google.com", then nothing.
I have added some permissions to the manifest - it now starts:
<manifest android:versionCode="1"
android:versionName="1"
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.support.appnavigation">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:label="#string/app_name">
<activity android:name=".app.AppNavHomeActivity"
android:label="#string/app_nav_home_label">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Clearly I must be doing something wrong - can anyone put me right?
I think you forget add permission in your AndroidManifest file:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Read more about Manifest file here.
UPDATED:
Here is an example of manifes file from loopj github
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.loopj.android.http"
android:versionName="1.4.3"
android:versionCode="1">
<application
android:name="android_async_http">
</application>
<uses-sdk android:minSdkVersion="3" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
You can see INTERNET permission here.
Change AsyncHttpResponseHandler()
to TextHttpResponseHandler()
then your Overrides should be:
myClient.get(url, new TextHttpResponseHandler() {
#Override
public void onFailure(int i, Header[] headers, String s, Throwable throwable) {
}
#Override
public void onSuccess(int ii, Header[] headers, String s) {
}
}
Try to also add the onStart and onComplete methods to the callback.
The problem with the AsyncHttpClient is that it wont throw an error if your JSON returned is correctly encoded or not
e.g. I had the same problem as you but noticed that both the onSuccess and onComplete methods were being called but not success or failure. Found it to be the way my server was returning JSON. I was trying to return an associated string array that I created my self and missed the [] infont of the arrayname
Problem: $result = array('result'=>'OK');
Solution: $result[] = array('result'=>'OK');
Not saying yours would be the same syntax problem but it wouldn't hurt to look over what is being returned
Ok, I have been working on a Android application for a while. It's basicaly a RSS reciever. I use RSS to check the news, weather forecast, TV schedule and Horoscope.
Everything was fine while I was testing it on Android 2.3.3, 2.3.6 and even on 2.1; but when I sent it to my friend who has Android 4.0 it did not work. I was suspicious so I tested it on emulator. Nor 4.0, nor 4.1 Emulators can run it. Here I provide Manifest and one class. If anybody knows how to fix this, that will be great.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="XXX.XXXXX.XXX"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="14" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".Vodic"
android:label="#string/title_activity_pocetna" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Pomoc"
android:label="#string/m_tel_vodi_za_odlu_ne"
></activity>
<activity
android:name=".Pomocna"
android:label="#string/m_tel_vodi_za_odlu_ne"
></activity>
.
.
.
<activity
android:name=".TvRasporedTreca"
android:label="#string/m_tel_vodi_za_odlu_ne"
></activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<!-- Needed to check when the network connection changes -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
</manifest>
And here's one class:
public class Vodic extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pocetna);
Button tv = (Button)findViewById(R.id.tv);
Button vijesti = (Button)findViewById(R.id.vijesti);
Button horoskop = (Button)findViewById(R.id.horoskop);
Button vremenska_prognoza = (Button)findViewById(R.id.vremenska_prognoza);
Button o_aplikaciji = (Button)findViewById(R.id.o_aplikaciji);
Button pomoc = (Button)findViewById(R.id.pomoc);
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent fy=new Intent(getApplicationContext(), TV_Raspored.class);
startActivity(fy);
}
});
.
.
.
pomoc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent fy=new Intent(getApplicationContext(), Pomoc.class);
startActivity(fy);
}
});
}
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if(netInfo != null && netInfo.isConnected()) {
return true;
}
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_pocetna, menu);
return true;
}
}
So, to sum up. It works on 2.1 and 2.3.3 but doesn't on 4.0 and 4.1 . I have no Idea what's wrong.. so if anybody knows, please help..
From Android 3.x and onward Google has added some checks that generate errors if your application employs very bad practices.
Without a log it is hard to confirm, but the most likely scenario is that you are making network operations in the core of your activities, generating a NetworkOnUIThread exception.
It is NOT a bug in the Android framework. The problem is that your activities run in the main thread, ie the UI thread.
So when you make a network call in an Activity, the whole UI freezes until you get an answer (or a timeout); which is something that you absolutely want to avoid.
An easy solution to this issue is to use AsyncTask : it is an easy to implement built-in solutions to make operations in a secondary thread.
Using the guide on JSoup's website I wrote the following code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
Document doc = Jsoup.connect("http://google.com").get();
Elements links = doc.getElementsByTag("a");
for(Element ele : links){
Log.i("Menu", ele.text());
}
} catch (IOException e) {
}
setContentView(R.layout.main);
}
I added the internet permission in my manifest file but it keeps throwing an IOException!
I tested your code and it should work fine... I would imagine your permission was put in the wrong spot. It goes BEFORE your application definition in your manifest:
here are the first few lines of my manifest that runs your code:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application android:icon="#drawable/icon" android:label="#string/app_name">