7android怎么了?
What's wrong with 7 android?
我有接收 udp 数据报套接字的服务
private void startServer(final UdpServerListener listener) {
mStarted = true;
mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
Looper myLooper = Looper.myLooper();
new HandlerThread("TcpServerThread") {
@Override
protected void onLooperPrepared() {
new Handler(getLooper()).post(() -> {
try {
byte[] data = new byte[8 * 1024];
InetAddress address = BnjUtils.getLocalIpAddress();
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
mServerSocket = new DatagramSocket(0, address);
final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
final int port = mServerSocket.getLocalPort();
while (mStarted) {
try {
mServerSocket.receive(datagramPacket); // blocks until something is received
/*
* Send bytes to app module.
*/
byte[] receiveData = new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
//POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER
new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));
} catch (IOException e) {
new Handler(myLooper).post(() -> listener.onServerStartFailed(e));
}
}
} catch (SocketException e) {
Log.e(mTag, "Socket Exception");
} finally {
if (mServerSocket != null && !mServerSocket.isClosed()) {
mServerSocket.close();
}
getLooper().quitSafely();
}
});
}
}.start();
}
因此结果数据 i post 通过 Binder
发送给监听器
//POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER
new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));
看看我的听众:
@NonNull
private UdpServerService.UdpServerListener getUdpServerServiceListener() {
if (mUdpServerServiceListener == null) {
mUdpServerServiceListener = new UdpServerService.UdpServerListener() {
@Override
public void onReceive(final byte[] bytes, final InetAddress inetAddress) {
if (mSocketListener != null && mListenerLooper != null) {
//TRY TO RECEIVW MY DATA HERE
}
}
};
}
return mUdpServerServiceListener;
}
查看我的服务连接 class 与活页夹
private class MyServiceConnection implements ServiceConnection {
UdpServerService.UdpServerBinder binder;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof UdpServerService.UdpServerBinder && mServerState == SERVER_STARTED) {
binder = (UdpServerService.UdpServerBinder) service;
binder.setListener(getUdpServerServiceListener());
binder.startServer();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//do something on disconnect
}
所以,这一切都很好,但在版本 5 和 6 的旧设备中 Android。
但在我的 GalaxyS7 或我的 Asus Zenfone 3 中
with Android 7 application freezes
并且在未停止之前不会响应用户触摸。
可能触发了一些限制机制,但我对此一无所知。
可能是错误的build.gradle
看到了
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'idea'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
useLibrary 'org.apache.http.legacy'
}
buildTypes {
debug {
minifyEnabled false
debuggable true
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
packagingOptions{
exclude 'META-INF/rxjava.properties'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//gson parser
implementation 'com.google.code.gson:gson:2.8.0'
//kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
// rxjava
implementation 'io.reactivex:rxjava:1.1.6'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.artemzin.rxjava:proguard-rules:1.1.0.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.8'
//help to avoid memory leaks
implementation 'com.badoo.mobile:android-weak-handler:1.0'
//guava for Android:
implementation 'com.google.guava:guava:23.6-android'
}
kotlin {
experimental {
coroutines "enable"
}
}
我的解决方案是简化这段代码,只需要在简单的线程中接收数据,post它的数据在同一个线程中:
void startServer() {
mStarted = true;
mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
new Thread(() -> {
try {
byte[] data = new byte[8 * 1024];//bucketful with fix size
InetAddress address = BnjUtils.getLocalIpAddress();
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
mServerSocket = new DatagramSocket(0, address);
final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
final int port = mServerSocket.getLocalPort();
mListener.onServerCreated(localAddress, port);
while (mStarted) {
try {
mServerSocket.receive(datagramPacket); // blocks until something is received
/*
* Send bytes to app module.
*/
byte[] receiveData = new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
mListener.onReceive(receiveData, datagramPacket.getAddress());
} catch (IOException e) {
mListener.onServerStartFailed(e);
}
}
} catch (SocketException e) {
Log.e(mTag, "Socket Exception");
} finally {
if (mServerSocket != null && !mServerSocket.isClosed()) {
mServerSocket.close();
}
}
}).start();
}
所以现在,工作没有冻结。
我有接收 udp 数据报套接字的服务
private void startServer(final UdpServerListener listener) {
mStarted = true;
mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
Looper myLooper = Looper.myLooper();
new HandlerThread("TcpServerThread") {
@Override
protected void onLooperPrepared() {
new Handler(getLooper()).post(() -> {
try {
byte[] data = new byte[8 * 1024];
InetAddress address = BnjUtils.getLocalIpAddress();
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
mServerSocket = new DatagramSocket(0, address);
final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
final int port = mServerSocket.getLocalPort();
while (mStarted) {
try {
mServerSocket.receive(datagramPacket); // blocks until something is received
/*
* Send bytes to app module.
*/
byte[] receiveData = new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
//POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER
new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));
} catch (IOException e) {
new Handler(myLooper).post(() -> listener.onServerStartFailed(e));
}
}
} catch (SocketException e) {
Log.e(mTag, "Socket Exception");
} finally {
if (mServerSocket != null && !mServerSocket.isClosed()) {
mServerSocket.close();
}
getLooper().quitSafely();
}
});
}
}.start();
}
因此结果数据 i post 通过 Binder
发送给监听器 //POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER
new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));
看看我的听众:
@NonNull
private UdpServerService.UdpServerListener getUdpServerServiceListener() {
if (mUdpServerServiceListener == null) {
mUdpServerServiceListener = new UdpServerService.UdpServerListener() {
@Override
public void onReceive(final byte[] bytes, final InetAddress inetAddress) {
if (mSocketListener != null && mListenerLooper != null) {
//TRY TO RECEIVW MY DATA HERE
}
}
};
}
return mUdpServerServiceListener;
}
查看我的服务连接 class 与活页夹
private class MyServiceConnection implements ServiceConnection {
UdpServerService.UdpServerBinder binder;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof UdpServerService.UdpServerBinder && mServerState == SERVER_STARTED) {
binder = (UdpServerService.UdpServerBinder) service;
binder.setListener(getUdpServerServiceListener());
binder.startServer();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//do something on disconnect
}
所以,这一切都很好,但在版本 5 和 6 的旧设备中 Android。
但在我的 GalaxyS7 或我的 Asus Zenfone 3 中
with Android 7 application freezes
并且在未停止之前不会响应用户触摸。
可能触发了一些限制机制,但我对此一无所知。
可能是错误的build.gradle 看到了
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'idea'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
useLibrary 'org.apache.http.legacy'
}
buildTypes {
debug {
minifyEnabled false
debuggable true
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
packagingOptions{
exclude 'META-INF/rxjava.properties'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//gson parser
implementation 'com.google.code.gson:gson:2.8.0'
//kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
// rxjava
implementation 'io.reactivex:rxjava:1.1.6'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.artemzin.rxjava:proguard-rules:1.1.0.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.8'
//help to avoid memory leaks
implementation 'com.badoo.mobile:android-weak-handler:1.0'
//guava for Android:
implementation 'com.google.guava:guava:23.6-android'
}
kotlin {
experimental {
coroutines "enable"
}
}
我的解决方案是简化这段代码,只需要在简单的线程中接收数据,post它的数据在同一个线程中:
void startServer() {
mStarted = true;
mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
new Thread(() -> {
try {
byte[] data = new byte[8 * 1024];//bucketful with fix size
InetAddress address = BnjUtils.getLocalIpAddress();
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
mServerSocket = new DatagramSocket(0, address);
final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
final int port = mServerSocket.getLocalPort();
mListener.onServerCreated(localAddress, port);
while (mStarted) {
try {
mServerSocket.receive(datagramPacket); // blocks until something is received
/*
* Send bytes to app module.
*/
byte[] receiveData = new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
mListener.onReceive(receiveData, datagramPacket.getAddress());
} catch (IOException e) {
mListener.onServerStartFailed(e);
}
}
} catch (SocketException e) {
Log.e(mTag, "Socket Exception");
} finally {
if (mServerSocket != null && !mServerSocket.isClosed()) {
mServerSocket.close();
}
}
}).start();
}
所以现在,工作没有冻结。