Open Zacharia2 opened 1 week ago
implementation("io.milton:milton-server-ce:4.0.2.2101")
使用viewflow或者使用material2
在Java中,你可以使用static final
关键字来定义常量。对于上面的例子,我们可以为每个位掩码定义一个常量,这样代码会更容易阅读和维护。以下是如何定义这些常量的示例:
public class NetworkUtils {
// 定义位掩码常量
public static final int MASK_WIFI = 0x01; // 0000 0001
public static final int MASK_ETHERNET = 0x02; // 0000 0010
public static final int MASK_MOBILE = 0x04; // 0000 0100
public static final int MASK_LOOPBACK = 0x08; // 0000 1000
public static final int MASK_BLUETOOTH_PAN = 0x10; // 0001 0000
public static final int MASK_WLAN = 0x20; // 0010 0000
public static final int MASK_ALL = 0xFF; // 1111 1111
// 其他方法...
}
在上面的代码中,0x01
、0x02
、0x04
、0x08
、0x10
、0x20
、0xFF
是十六进制表示法,它们分别对应于二进制的0000 0001
、0000 0010
、0000 0100
、0000 1000
、0001 0000
、0010 0000
和1111 1111
。这些值被赋给常量,以表示不同的网络接口类型。
现在,你可以在原来的代码中使用这些常量,而不是直接使用数字:
ArrayList<String> retValue = new ArrayList<>();
try {
String wifiAddr = getWifiIpAddress(context);
if ((mask & MASK_WIFI) == MASK_WIFI && wifiAddr != null) {
retValue.add(wifiAddr);
}
Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
NetworkInterface intf = en.nextElement();
if (((mask & MASK_ETHERNET) == MASK_ETHERNET && intf.getDisplayName().startsWith("eth")) ||
((mask & MASK_MOBILE) == MASK_MOBILE && (intf.getDisplayName().startsWith("pdp") || intf.getDisplayName().startsWith("rmnet"))) ||
((mask & MASK_LOOPBACK) == MASK_LOOPBACK && intf.getDisplayName().startsWith("lo")) ||
((mask & MASK_BLUETOOTH_PAN) == MASK_BLUETOOTH_PAN && intf.getDisplayName().startsWith("bt-pan")) ||
((mask & MASK_WLAN) == MASK_WLAN && intf.getDisplayName().startsWith("wl")) ||
mask == MASK_ALL) {
Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();
while (enumIpAddr.hasMoreElements()) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (inetAddress instanceof Inet4Address) {
String ipAddr = inetAddress.getHostAddress().toString();
if (wifiAddr == null || !wifiAddr.equals(ipAddr)) {
retValue.add(ipAddr);
}
}
}
}
}
} catch (SocketException ex) {
ex.printStackTrace();
}
return retValue;
使用常量可以使代码更清晰,更易于理解,并且如果将来需要修改掩码值,你只需在一个地方进行更改,而不必在代码库中搜索并替换所有出现的数字。
我已经查看了您提供的链接中的源代码。以下是需要在该代码中使用的权限:
这些权限需要在AndroidManifest.xml
文件中声明,并且如果您的应用目标API级别是23或以上,还需要在运行时请求这些权限。
以下是权限声明的示例:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xinglan.webdavserver">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 其他权限和组件声明 -->
</manifest>
请确保在代码中适当地检查和请求这些权限。
AndroidX 是一个开源库的集合,它为Android开发者提供了一套向后兼容的Jetpack组件库。这些库是Android支持库(Support Library)的替代品,旨在提供更加一致、功能丰富且易于使用的API,以便开发者能够更容易地构建优秀的Android应用程序。
以下是AndroidX的一些关键点:
向后兼容性:AndroidX库设计用于向后兼容,这意味着使用AndroidX库的应用程序可以在旧的Android版本上运行,而不会丢失任何功能。
Jetpack组件:AndroidX是Jetpack的一部分,它包含了Jetpack中的许多组件,例如LiveData、ViewModel、Room、Navigation、WorkManager等。
重构的包名:与Android支持库不同,AndroidX库的包名已经重构,不再使用android.support
前缀。新的包名以androidx
开头,例如androidx.appcompat
、androidx.recyclerview
等。
统一的版本管理:AndroidX库使用统一的版本号,这使得依赖项管理变得更加简单。开发者只需为所有AndroidX库指定一个版本号,而不是为每个单独的库指定。
持续更新和改进:AndroidX库会定期更新,以包含最新的功能和修复,确保开发者能够利用最新的Android平台特性。
迁移工具:Google提供了迁移工具,帮助开发者将现有的项目从Android支持库迁移到AndroidX。
为什么要使用AndroidX?
为了开始使用AndroidX,你需要在项目的build.gradle
文件中进行一些配置,并可能需要迁移现有的代码库。Google提供了详细的迁移指南来帮助开发者完成这一过程。
是的,这段代码中使用了一些过时的方法和API。以下是对这段代码的更新,以使用最新的Android通知API(基于Android API level 26及以上):
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
private void showNotification(String className, int notificationTextId, int notificationIconId, int notificationStartedTitleId, int notificationStartedTextId, String ipDetail, boolean startForeground) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "your_channel_id"; // 创建通知渠道时使用的ID
String channelName = "Your Channel Name"; // 用户可见的通知渠道名称
// 创建通知渠道(仅在Android O及以上版本需要)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
Intent startIntent = new Intent();
startIntent.setClassName(this, className);
startIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, startIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
Notification.Builder builder = new Notification.Builder(this, channelId)
.setTicker(getString(notificationTextId))
.setContentTitle(getString(notificationStartedTitleId))
.setContentText(ipDetail)
.setSmallIcon(notificationIconId)
.setContentIntent(pendingIntent)
.setStyle(new Notification.BigTextStyle().bigText(ipDetail))
.setAutoCancel(true);
Notification notification = builder.build();
if (startForeground) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_STARTED_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
} else {
startForeground(NOTIFICATION_STARTED_ID, notification);
}
} else {
notificationManager.notify(1, notification);
}
}
请注意以下几点更改:
Notification.Builder
来构建通知。NotificationChannel
类来创建通知渠道。startForeground
方法时,如果API版本大于等于Android O,则可以使用ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE
参数。notification.flags |= 34;
这行代码,因为通知的行为可以通过Notification.Builder
设置,例如使用.setAutoCancel(true)
来让通知在点击后自动取消。请根据您的具体需求调整channelId
和channelName
。
在提供的代码中,我已更新了主要的API以使用最新的通知构建方法。然而,还有一些其他的小细节和最佳实践可以考虑:
使用NotificationCompat.Builder
来支持更广泛的Android版本:
如果你需要支持低于API level 26的Android版本,应该使用NotificationCompat.Builder
而不是Notification.Builder
。
设置正确的标志:
之前使用的notification.flags |= 34;
包含了Notification.FLAG_SHOW_LIGHTS
和Notification.FLAG_AUTO_CANCEL
。现在,这些可以通过Notification.Builder
设置。
使用startForeground
的第三个参数:
在Android O及以上版本,startForeground
方法可以接受一个额外的参数,表示前台服务的类型。
下面是进一步更新后的代码示例,使用NotificationCompat.Builder
来兼容旧版本:
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
private void showNotification(String className, int notificationTextId, int notificationIconId, int notificationStartedTitleId, int notificationStartedTextId, String ipDetail, boolean startForeground) {
Context context = getApplicationContext();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "your_channel_id"; // 创建通知渠道时使用的ID
String channelName = "Your Channel Name"; // 用户可见的通知渠道名称
// 创建通知渠道(仅在Android O及以上版本需要)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
Intent startIntent = new Intent();
startIntent.setClassName(context, className);
startIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
.setTicker(getString(notificationTextId))
.setContentTitle(getString(notificationStartedTitleId))
.setContentText(ipDetail)
.setSmallIcon(notificationIconId)
.setContentIntent(pendingIntent)
.setStyle(new NotificationCompat.BigTextStyle().bigText(ipDetail))
.setAutoCancel(true);
Notification notification = builder.build();
if (startForeground) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_STARTED_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
} else {
startForeground(NOTIFICATION_STARTED_ID, notification);
}
} else {
NotificationManagerCompat.from(context).notify(1, notification);
}
}
请确保你已经在你的项目中添加了androidx.core:core
库,因为NotificationCompat
是AndroidX库的一部分。如果你的项目还没有迁移到AndroidX,你需要使用android.support.v4.app.NotificationCompat
代替androidx.core.app.NotificationCompat
。
此外,请确保在AndroidManifest.xml中正确声明了服务以及任何需要的权限。
implementation("xerces:xercesImpl:2.12.2")
implementation("com.ettrema:milton-api:1.8.1.4")