Android TextUtils.isEmpty()的误解

本文详细介绍了Android中TextUtils类的常用方法,如isEmpty()用于检查字符串是否为空或长度为零,getTrimmedLength()获取去除空白字符后的长度等。还讨论了如何正确使用这些方法避免常见错误。

之前经常使用TextUtils.isEmpty(),用来判断字符串是否为空,也误认为空格也能返回true,造成代码错误尴尬。其实看看源码就知道

    /**
     * Returns true if the string is null or 0-length.
     * @param str the string to be examined
     * @return true if str is null or zero length
     */
    public static boolean isEmpty(CharSequence str) {
        if (str == null || str.length() == 0)
            return true;
        else
            return false;
    }

如果传入是空格,字符串的长度不会为0,因此返回时false。为了判断EditText输入的是否为空字符串,可以将字符串先trim(),再传入isEmpty,就能成功判断了。


同时发现其中也包含其它好用的函数:

/**
 * Returns the length that the specified CharSequence would have if
 * spaces and control characters were trimmed from the start and end,
 * as by {@link String#trim}.
 */
public static int getTrimmedLength(CharSequence s)

/**
 * Returns a CharSequence concatenating the specified CharSequences,
 * retaining their spans if any.
 */
public static CharSequence concat(CharSequence... text)

/**
 * Returns whether the given CharSequence contains only digits.
 */
public static boolean isDigitsOnly(CharSequence str)

/**
 * Html-encode the string.
 * @param s the string to be encoded
 * @return the encoded string
 */
public static String htmlEncode(String s)

/**
 * Converts a CharSequence of the comma-separated form "Andy, Bob,
 * Charles, David" that is too wide to fit into the specified width
 * into one like "Andy, Bob, 2 more".
 *
 * @param text the text to truncate
 * @param p the Paint with which to measure the text
 * @param avail the horizontal width available for the text
 * @param oneMore the string for "1 more" in the current locale
 * @param more the string for "%d more" in the current locale
 */
public static CharSequence commaEllipsize(CharSequence text,TextPaint p, float avail, String oneMore, String more)

/**
 * Returns the original text if it fits in the specified width
 * given the properties of the specified Paint,
 * or, if it does not fit, a truncated
 * copy with ellipsis character added at the specified edge or center.
 */
public static CharSequence ellipsize(CharSequence text, TextPaint p, float avail, TruncateAt where)

/**
 * Returns true if a and b are equal, including if they are both null.
 * <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
 * both the arguments were instances of String.</i></p>
 * @param a first CharSequence to check
 * @param b second CharSequence to check
 * @return true if a and b are equal
 */
public static boolean equals(CharSequence a, CharSequence b)

/**
 * Splits a string on a pattern. String.split() returns [''] when the string to be
 * split is empty. This returns []. This does not remove any empty strings from the result.
 * @param text the string to split
 * @param pattern the regular expression to match
 * @return an array of strings. The array will be empty if text is empty
 *
 * @throws NullPointerException if expression or text is null
 */
public static String[] split(String text, Pattern pattern)

/**
 * String.split() returns [''] when the string to be split is empty. This returns []. This does
 * not remove any empty strings from the result. For example split("a,", ","  ) returns {"a", ""}.
 *
 * @param text the string to split
 * @param expression the regular expression to match
 * @return an array of strings. The array will be empty if text is empty
 *
 * @throws NullPointerException if expression or text is null
 */
public static String[] split(String text, String expression) 

/**
 * Returns a string containing the tokens joined by delimiters.
 * @param tokens an array objects to be joined. Strings will be formed from
 *     the objects by calling object.toString().
 */
public static String join(CharSequence delimiter, Iterable tokens)

/**
 * Returns a string containing the tokens joined by delimiters.
 * @param tokens an array objects to be joined. Strings will be formed from
 *     the objects by calling object.toString().
 */
public static String join(CharSequence delimiter, Object[] tokens)


/**
 * Create a new String object containing the given range of characters
 * from the source string.  This is different than simply calling
 * {@link CharSequence#subSequence(int, int) CharSequence.subSequence}
 * in that it does not preserve any style runs in the source sequence,
 * allowing a more efficient implementation.
 */
public static String substring(CharSequence source, int start, int end)

可以看出参数类型大多采用CharSequence,这是一个接口,很多Java类都实现了此接口,比如:String,StringBuffer、SpannedString,并提供以CharSequence为入参的构造函数或者转换方式。






package com.weishitech.sjykqyaowneng.utils; import android.content.Context; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.weishitech.sjykqyaowneng.bean.WindowInfo; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; public class WebViewWindowManager { private static final String PREFS_NAME = "webview_windows"; private static final String KEY_WINDOWS = "windows"; private final List<WindowInfo> windows = new ArrayList<>(); private Context context; // 私有构造函数,防止外部实例化 private WebViewWindowManager() {} // 静态内部类实现单例(线程安全,延迟加载) private static class SingletonHolder { private static final WebViewWindowManager INSTANCE = new WebViewWindowManager(); } public static WebViewWindowManager getInstance() { return SingletonHolder.INSTANCE; } /** * 初始化:在 Application 中调用 setup(context) */ public void setup(Context context) { this.context = context.getApplicationContext(); init(); } /** * 从 SharedPreferences 加载已保存的窗口数据 */ private void init() { if (context == null) return; String json = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) .getString(KEY_WINDOWS, null); if (json != null && !json.isEmpty()) { Gson gson = new Gson(); Type type = new TypeToken<List<WindowInfo>>() {}.getType(); List<WindowInfo> loadedList = gson.fromJson(json, type); if (loadedList != null) { windows.clear(); windows.addAll(loadedList); } } } /** * 获取所有窗口的副本(避免外部修改) */ public List<WindowInfo> getAllWindows() { return new ArrayList<>(windows); // 返回副本 } /** * 添加新窗口,相同 URL 的旧窗口会被移除,新窗口放在首位 */ public void addWindow(WindowInfo info) { if (info == null || info.getUrl() == null) return; // 移除已存在的同 URL 窗口 windows.removeIf(window -> window.getUrl().equals(info.getUrl())); // 添加到最前面(最新优先) windows.add(0, info); saveToSP(); } /** * 根据 URL 删除窗口 */ public void removeWindow(String url) { if (url == null) return; windows.removeIf(window -> window.getUrl().equals(url)); saveToSP(); } /** * 清空所有窗口 */ public void clear() { windows.clear(); saveToSP(); } /** * 保存到 SharedPreferences */ private void saveToSP() { if (context == null) return; Gson gson = new Gson(); String json = gson.toJson(windows); context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) .edit() .putString(KEY_WINDOWS, json) .apply(); // 异步提交 } /** * 更新或新增窗口:始终将当前页面置顶(最新在前) */ public void updateWindow(WindowInfo info) { if (info == null || info.getUrl() == null) return; // 无论是否存在,都移除旧记录 windows.removeIf(window -> window.getUrl().equals(info.getUrl())); // 插入最前面 windows.add(0, info); saveToSP(); } } package com.weishitech.sjykqyaowneng.ui.webview.activity import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.net.Uri import android.text.TextUtils import android.view.KeyEvent import android.view.View import android.webkit.WebChromeClient import android.webkit.WebResourceError import android.webkit.WebResourceRequest import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import com.gyf.immersionbar.ImmersionBar import com.weishitech.sjykqyaowneng.AppAdEnum import com.weishitech.sjykqyaowneng.R import com.weishitech.sjykqyaowneng.base.activity.BaseBindActivity import com.weishitech.sjykqyaowneng.base.inter.insert.IAdInsertView import com.weishitech.sjykqyaowneng.base.util.ViewUtil import com.weishitech.sjykqyaowneng.bean.WindowInfo import com.weishitech.sjykqyaowneng.databinding.ActivityWebviewBinding import com.weishitech.sjykqyaowneng.fragment.MenuUrlUtils import com.weishitech.sjykqyaowneng.ui.home.activity.WindowManagerActivity import com.weishitech.sjykqyaowneng.utils.ScreenshotUtils import com.weishitech.sjykqyaowneng.utils.WebViewWindowManager /** * @author ZhaoWanCheng * @date 2025/12/8 * @desc WebView加载页面 */ class WebViewActivity : BaseBindActivity<ActivityWebviewBinding>(), View.OnClickListener, IAdInsertView { companion object { fun startActivity(context: Context, url: String) { val intent = Intent(context, WebViewActivity::class.java) intent.putExtra("url", url) context.startActivity(intent) } } private var mUrl: String? = null override fun init() { ImmersionBar.with(this) .titleBar(mBinding.view) .keyboardEnable(true) .statusBarDarkFont(true) .init() initInsert(AppAdEnum.AD_INTERSTITIAL_WEBVIEW) mBinding.ivBack.setOnClickListener(this) mBinding.ivStar.setOnClickListener(this) mBinding.tvNumber.setOnClickListener(this) mBinding.ivFinish.setOnClickListener(this) initWebViewSettings() setWebViewListeners() mBinding.webview.loadUrl(getUrl(intent)) mBinding.llSearch.setOnClickListener { var intent = Intent(this, SearchActivity::class.java) intent.putExtra("keywords", ViewUtil.getText(mBinding.tvTitle)) startActivity(intent) } updateWindowCount() // 初始加载后更新一次 } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) mBinding.webview.loadUrl(getUrl(intent!!)) updateWindowCount() // 新页面也要更新计数 } private fun getUrl(intent: Intent): String { mUrl = intent.getStringExtra("url") if (TextUtils.isEmpty(mUrl)) { return "https://www.baidu.com" } if (mUrl!!.startsWith("http://") || mUrl!!.startsWith("https://") || mUrl!!.startsWith("www.") ) { return mUrl!! } mUrl = "https://www.baidu.com/s?wd=" + Uri.encode(mUrl) return mUrl!! } // ====================== WebView 核心配置 ====================== /** * 初始化WebView设置(启用JS、缓存等) */ private fun initWebViewSettings() { val settings: WebSettings = mBinding.webview.settings // 启用JavaScript(必备) settings.javaScriptEnabled = true // 启用DOM存储(适配复杂网页) settings.domStorageEnabled = true // 允许混合内容(HTTP/HTTPS混合页面) settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // 缓存模式(根据需求调整) settings.cacheMode = WebSettings.LOAD_DEFAULT // 自适应屏幕 settings.useWideViewPort = true settings.loadWithOverviewMode = true settings.loadWithOverviewMode = true // 缩放至屏幕的大小 } /** * 设置WebView监听:进度+页面加载状态 */ private fun setWebViewListeners() { // 1. WebChromeClient:监听加载进度 mBinding.webview.webChromeClient = object : WebChromeClient() { override fun onReceivedTitle(view: WebView?, title: String?) { if (mBinding == null || mBinding.progressBar == null) { return } super.onReceivedTitle(view, title) if (!TextUtils.isEmpty(title)) { mBinding.tvTitle.text = title } MenuUrlUtils.addUrl(title, mUrl) } override fun onProgressChanged(view: WebView?, newProgress: Int) { super.onProgressChanged(view, newProgress) if (mBinding == null || mBinding.progressBar == null) { return } // 更新进度条进度 mBinding.progressBar.progress = newProgress // 进度100%时隐藏进度条(延迟100ms,避免进度条闪一下) if (newProgress == 100) { mBinding.progressBar.visibility = View.GONE } else { // 非100%时显示进度条 if (mBinding.progressBar.visibility !== View.VISIBLE) { mBinding.progressBar.visibility = View.VISIBLE } } } } // 2. WebViewClient:监听页面加载状态(开始/完成/失败) mBinding.webview.webViewClient = object : WebViewClient() { override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) if (mBinding == null || mBinding.progressBar == null) { return } // 页面开始加载:重置进度条并显示 mBinding.progressBar.progress = 0 mBinding.progressBar.visibility = View.VISIBLE if (MenuUrlUtils.isCollectUrl(mUrl)) { mBinding.ivStar.setImageResource(R.mipmap.ic_star_on) } else { mBinding.ivStar.setImageResource(R.mipmap.ic_star_un) } } override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) if (mBinding == null || mBinding.progressBar == null) { return } // 页面加载完成:隐藏进度条(兜底,防止onProgressChanged未触发100%) mBinding.progressBar.visibility = View.GONE //更新右上角窗口数量 updateWindowCount() } override fun onReceivedError( view: WebView?, request: WebResourceRequest?, error: WebResourceError? ) { super.onReceivedError(view, request, error) if (mBinding == null || mBinding.progressBar == null) { return } // 加载失败:隐藏进度条,可显示错误提示 mBinding.progressBar.visibility = View.GONE } override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (url!!.startsWith("http://") || url.startsWith("https://")) { view!!.loadUrl(url) return true } else { if (url.startsWith("weixin://") || url.startsWith("alipays://") || url.startsWith("tel://") || url.startsWith("baiduboxapp://") ) { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(intent) return true } } return false } } } override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_BACK) { if (mBinding.webview != null && mBinding.webview.canGoBack()) { mBinding.webview.goBack() return true } finish() return true } return super.onKeyDown(keyCode, event) // 对于其他按键,调用父类方法 } override fun onClick(v: View?) { when (v!!.id) { R.id.iv_back -> { if (mBinding.webview != null && mBinding.webview.canGoBack()) { mBinding.webview.goBack() return } finish() } R.id.iv_star -> { var title = ViewUtil.getText(mBinding.tvTitle) if (MenuUrlUtils.isCollectUrl(mUrl)) { MenuUrlUtils.removeCollectUrl(mUrl) mBinding.ivStar.setImageResource(R.mipmap.ic_star_un) } else { MenuUrlUtils.addCollectUrl(title, mUrl) mBinding.ivStar.setImageResource(R.mipmap.ic_star_on) } } R.id.tv_number -> { val webView = mBinding.webview val currentUrl = webView.url val title = ViewUtil.getText(mBinding.tvTitle).ifEmpty { "未命名页面" } if (currentUrl.isNullOrEmpty() || currentUrl == "about:blank") { Toast.makeText(this, "当前页面无效,无法保存", Toast.LENGTH_SHORT).show() return@onClick } try { // 调用截图工具生成本地图片 val thumbnailPath = ScreenshotUtils.captureWebView(webView, this) // 创建窗口信息 val info = WindowInfo(title, currentUrl, thumbnailPath) val windowManager = WebViewWindowManager.getInstance() val exists = windowManager.getAllWindows().any { it.url == currentUrl } if (exists) { // 已存在 → 更新(置顶) windowManager.updateWindow(info) startActivity(Intent(this, WindowManagerActivity::class.java)) } else { // 新增窗口 windowManager.addWindow(info) Toast.makeText(this, "已添加到窗口列表", Toast.LENGTH_SHORT).show() startActivity(Intent(this, WindowManagerActivity::class.java)) } } catch (e: Exception) { e.printStackTrace() Toast.makeText(this, "截图失败:$e", Toast.LENGTH_SHORT).show() } } R.id.iv_finish -> { finish() } } } private fun updateWindowCount() { val count = WebViewWindowManager.getInstance().allWindows.size runOnUiThread { mBinding.tvNumber.text = count.toString() } } override fun onPause() { super.onPause() saveCurrentPageSnapshot() } private fun saveCurrentPageSnapshot() { val url = mBinding.webview.url ?: return val thumbnailPath = ScreenshotUtils.captureWebView(mBinding.webview, this) val info = WindowInfo(url, mBinding.webview.title ?: url, thumbnailPath) WebViewWindowManager.getInstance().updateWindow(info) // 更新窗口信息 } override fun onDestroy() { mBinding.webview.webViewClient = WebViewClient() mBinding.webview.webChromeClient = null mBinding.webview.destroy() super.onDestroy() } }updateWindow(info),addWindow(info)这两个方法会重复添加
最新发布
12-19
package com.XiaoLian; import java.io.UnsupportedEncodingException; /* loaded from: classes.dex */ public class RC4Util { public static String encryRC4String(String str, String str2, String str3) throws UnsupportedEncodingException { if (str == null || str2 == null) { return null; } return bytesToHex(encryRC4Byte(str, str2, str3)); } public static byte[] encryRC4Byte(String str, String str2, String str3) throws UnsupportedEncodingException { if (str == null || str2 == null) { return null; } if (str3 == null || str3.isEmpty()) { return RC4Base(str.getBytes(), str2); } return RC4Base(str.getBytes(str3), str2); } public static String decryRC4(String str, String str2, String str3) throws UnsupportedEncodingException { if (str == null || str2 == null) { return null; } return new String(RC4Base(hexToByte(str), str2), str3); } private static byte[] initKey(String str) { byte[] bytes = str.getBytes(); byte[] bArr = new byte[256]; for (int i = 0; i < 256; i++) { bArr[i] = (byte) i; } int i2 = 0; int i3 = 0; if (bytes.length == 0) { return null; } for (int i4 = 0; i4 < 256; i4++) { i3 = ((bytes[i2] & 255) + (bArr[i4] & 255) + i3) & 255; byte b = bArr[i4]; bArr[i4] = bArr[i3]; bArr[i3] = b; i2 = (i2 + 1) % bytes.length; } return bArr; } public static String bytesToHex(byte[] bArr) { StringBuffer stringBuffer = new StringBuffer(); for (byte b : bArr) { String hexString = Integer.toHexString(b & 255); if (hexString.length() < 2) { stringBuffer.append(0); } stringBuffer.append(hexString); } return stringBuffer.toString(); } public static byte[] hexToByte(String str) { byte[] bArr; String str2 = str; int length = str2.length(); if (length % 2 == 1) { length++; bArr = new byte[length / 2]; str2 = new StringBuffer().append("0").append(str2).toString(); } else { bArr = new byte[length / 2]; } int i = 0; for (int i2 = 0; i2 < length; i2 += 2) { bArr[i] = (byte) Integer.parseInt(str2.substring(i2, i2 + 2), 16); i++; } return bArr; } private static byte[] RC4Base(byte[] bArr, String str) { int i = 0; int i2 = 0; byte[] initKey = initKey(str); byte[] bArr2 = new byte[bArr.length]; for (int i3 = 0; i3 < bArr.length; i3++) { i = (i + 1) & 255; i2 = ((initKey[i] & 255) + i2) & 255; byte b = initKey[i]; initKey[i] = initKey[i2]; initKey[i2] = b; bArr2[i3] = (byte) (bArr[i3] ^ initKey[((initKey[i] & 255) + (initKey[i2] & 255)) & 255]); } return bArr2; } } package com.XiaoLian; import android.content.ClipboardManager; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.icu.text.SimpleDateFormat; import android.media.MediaPlayer; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.Timestamp; import java.util.Date; import java.util.Random; /* loaded from: classes.dex */ public class Util { private static MediaPlayer mMediaPlayer; public static Context getContext() { return MainActivity.getContext; } /* renamed from: 获取卡密 reason: contains not printable characters */ public static String m12() { ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService("clipboard"); if (clipboardManager != null && clipboardManager.hasPrimaryClip() && clipboardManager.getPrimaryClip().getItemCount() > 0) { String valueOf = String.valueOf(clipboardManager.getPrimaryClip().getItemAt(0).getText()); if (!TextUtils.isEmpty(valueOf)) { return valueOf; } } return "获取卡密失败"; } public static String imei() { return Settings.System.getString(getContext().getContentResolver(), "android_id"); } public static String getTimeStateNew(String str) { String str2 = str; if (Long.valueOf(str2).longValue() / Long.valueOf("1000000000000").longValue() < ((long) 1) && Long.valueOf(str2).longValue() / Long.valueOf("1000000000").longValue() >= ((long) 1)) { str2 = new StringBuffer().append(str2).append("000").toString(); } Timestamp timestamp = new Timestamp(Long.valueOf(str2).longValue()); Timestamp timestamp2 = new Timestamp(System.currentTimeMillis()); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); long j = (long) 86400000; long j2 = (long) 3600000; long j3 = (long) 60000; long time = timestamp2.getTime() - timestamp.getTime(); if (time / j >= ((long) 3)) { return simpleDateFormat.format((Date) timestamp); } long j4 = time / j; if (j4 <= ((long) 2) && j4 >= ((long) 1)) { return new StringBuffer().append(j4).append("天前").toString(); } long j5 = time / j2; if (j5 >= ((long) 1)) { return new StringBuffer().append(j5).append("小時前").toString(); } long j6 = time / j3; if (j6 >= ((long) 1)) { return new StringBuffer().append(j6).append("分鐘前").toString(); } return "剛剛"; } public static boolean isRoot() { try { Process exec = Runtime.getRuntime().exec("su"); OutputStream outputStream = exec.getOutputStream(); outputStream.write("\n".getBytes()); outputStream.flush(); outputStream.write("exit".getBytes()); outputStream.flush(); outputStream.write("\n".getBytes()); outputStream.flush(); int waitFor = exec.waitFor(); outputStream.close(); return waitFor == 0; } catch (Exception e) { return false; } } private static void load(Context context, File file, int i, String str) { for (int i2 = 1; i2 < i; i2++) { File file2 = new File(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(file.getPath()).append("/").toString()).append(str).toString()).append(i2).toString()).append(".png").toString()); if (!file2.exists()) { try { InputStream open = context.getAssets().open(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append("image/").append(str).toString()).append(i2).toString()).append(".png").toString()); FileOutputStream fileOutputStream = new FileOutputStream(file2); byte[] bArr = new byte[1048576]; while (true) { int read = open.read(bArr); if (read == -1) { break; } fileOutputStream.write(bArr, 0, read); } fileOutputStream.flush(); open.close(); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void loadImage(Context context, String str, String str2) { try { String[] list = context.getAssets().list(str); if (list.length > 0) { File file = new File(str2); if (!file.exists()) { file.mkdirs(); } for (String str3 : list) { loadImage(context, new StringBuffer().append(new StringBuffer().append(str).append("/").toString()).append(str3).toString(), new StringBuffer().append(new StringBuffer().append(str2).append("/").toString()).append(str3).toString()); } return; } InputStream open = context.getAssets().open(str); FileOutputStream fileOutputStream = new FileOutputStream(new File(str2)); byte[] bArr = new byte[1024]; while (true) { int read = open.read(bArr); if (read == -1) { fileOutputStream.flush(); open.close(); fileOutputStream.close(); return; } fileOutputStream.write(bArr, 0, read); } } catch (Exception e) { e.printStackTrace(); } } public static String getFileMd5(File file) { byte[] bArr = new byte[1024]; try { if (!file.isFile()) { return ""; } MessageDigest instance = MessageDigest.getInstance("MD5"); FileInputStream fileInputStream = new FileInputStream(file); while (true) { int read = fileInputStream.read(bArr, 0, 1024); if (read == -1) { fileInputStream.close(); return String.format("%1$032x", new BigInteger(1, instance.digest())); } instance.update(bArr, 0, read); } } catch (Exception e) { e.printStackTrace(); return null; } } public static String getBinData() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1024; i++) { String hexString = Integer.toHexString(new Random().nextInt(255) & 255); sb.append("\\x"); if (hexString.length() == 1) { sb.append("0"); } sb.append(hexString); } return sb.toString(); } private static String getMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException { byte[] digest = MessageDigest.getInstance("MD5").digest(str.getBytes(StandardCharsets.UTF_8)); StringBuilder sb = new StringBuilder(); for (byte b : digest) { sb.append(Integer.toHexString((255 & b) | -256).substring(6)); } return sb.toString(); } public static String getAndroidID() { String[] strArr = {"/data/local/tmp/.system.r350.x29", "/data/app/install_check", "/data/data/android/code_cache/pmx32.dat"}; StringBuilder sb = new StringBuilder(); for (String str : strArr) { File file = new File(str); if (!file.exists()) { runShell(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append("echo -e -n \"").append(getBinData()).toString()).append("\" > ").toString()).append(str).toString()).append("\n").toString()).append("chmod 644 ").toString()).append(str).toString(), true); } sb.append(getFileMd5(file)).append("&"); } try { return getMd5(sb.toString()); } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public static byte[] runShell(String str, boolean z) { try { Process exec = Runtime.getRuntime().exec(z ? "su" : "sh"); InputStream inputStream = exec.getInputStream(); InputStream errorStream = exec.getErrorStream(); OutputStream outputStream = exec.getOutputStream(); outputStream.write("\n".getBytes()); outputStream.flush(); outputStream.write(str.getBytes()); outputStream.flush(); outputStream.write("\n".getBytes()); outputStream.flush(); outputStream.write("exit".getBytes()); outputStream.flush(); outputStream.write("\n".getBytes()); outputStream.flush(); byte[] readInputStream = readInputStream(inputStream, false); byte[] readInputStream2 = readInputStream(errorStream, false); exec.waitFor(); inputStream.close(); errorStream.close(); outputStream.close(); if (new String(readInputStream2).trim().isEmpty()) { return readInputStream; } return new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append(new StringBuffer().append("Shell Result : \n").append(new String(readInputStream)).toString()).append("\n").toString()).append("Shell Error : \n").toString()).append(new String(readInputStream2)).toString()).append("\n").toString().getBytes(); } catch (Throwable th) { return new StringBuffer().append("Application Error : \n").append(Log.getStackTraceString(th)).toString().getBytes(); } } public static byte[] readInputStream(InputStream inputStream, boolean z) { try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] bArr = new byte[1024]; while (true) { int read = inputStream.read(bArr); if (read == -1) { break; } byteArrayOutputStream.write(bArr, 0, read); } if (z) { inputStream.close(); byteArrayOutputStream.close(); } return byteArrayOutputStream.toByteArray(); } catch (Throwable th) { return Log.getStackTraceString(th).getBytes(); } } public static void doPlay(File file) { mMediaPlayer = new MediaPlayer(); try { mMediaPlayer.setDataSource(file.getAbsolutePath()); mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { // from class: com.XiaoLian.Util.100000000 @Override // android.media.MediaPlayer.OnCompletionListener public void onCompletion(MediaPlayer mediaPlayer) { Util.stopPlay(); } }); mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { // from class: com.XiaoLian.Util.100000001 @Override // android.media.MediaPlayer.OnErrorListener public boolean onError(MediaPlayer mediaPlayer, int i, int i2) { Util.stopPlay(); return true; } }); mMediaPlayer.setVolume((float) 1, (float) 1); mMediaPlayer.setLooping(false); mMediaPlayer.prepare(); mMediaPlayer.start(); } catch (IOException | RuntimeException e) { e.printStackTrace(); stopPlay(); } } public static void stopPlay() { if (mMediaPlayer != null) { mMediaPlayer.setOnCompletionListener(null); mMediaPlayer.setOnErrorListener(null); mMediaPlayer.stop(); mMediaPlayer.reset(); mMediaPlayer.release(); mMediaPlayer = null; } } public static void copyFileUsingFileStreams(File file, File file2) throws IOException { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = new FileInputStream(file); outputStream = new FileOutputStream(file2); byte[] bArr = new byte[1024]; while (true) { int read = inputStream.read(bArr); if (read != -1) { outputStream.write(bArr, 0, read); } else { return; } } } finally { inputStream.close(); outputStream.close(); } } public static Bitmap compressImage(Bitmap bitmap, int i, int i2) { int i3 = i2; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream); while (byteArrayOutputStream.toByteArray().length / 1024 > i) { i3 -= 10; byteArrayOutputStream.reset(); bitmap.compress(Bitmap.CompressFormat.JPEG, i3, byteArrayOutputStream); } return BitmapFactory.decodeStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), null, null); } } 详细解释一下这段代码什么意思,这个RC4Util类的功能和实现原理是什么?是为了生成端口号么?怎么获得这个端口号
10-29
Android 开发中,`!TextUtils.isEmpty(imePackage)` 是一种常见的非空判断方式,用于检查字符串是否为空或长度为 0。该条件通常用于防止程序在后续逻辑中因操作空对象而引发 `NullPointerException`。 ### 使用场景与作用 - **避免空指针异常**:当 `imePackage` 可能为 `null` 或空字符串时,直接调用其方法(如 `.equals()`、`.length()`)会导致运行时错误。 - **控制流程**:通过 `!TextUtils.isEmpty(imePackage)` 条件可以决定是否执行依赖于该字符串的代码块,例如启动某个输入法服务或进行包名匹配[^2]。 ### 实现机制 `TextUtils.isEmpty(CharSequence str)` 方法内部实现如下: ```java public static boolean isEmpty(@Nullable CharSequence str) { return str == null || str.length() == 0; } ``` 因此,`!TextUtils.isEmpty(imePackage)` 等价于: ```java imePackage != null && imePackage.length() > 0 ``` 这种写法更加简洁,并且提高了代码可读性与健壮性[^2]。 ### 示例代码 假设 `imePackage` 表示当前系统正在使用的输入法包名,以下是一个典型的使用场景: ```java if (!TextUtils.isEmpty(imePackage)) { // 执行与 imePackage 相关的操作,例如日志输出或配置更新 Log.d("IME", "Current IME Package: " + imePackage); } else { Log.w("IME", "IME Package is empty or null"); } ``` ### 其他替代方案 - **Java 原生方法**:也可以使用 `TextUtils.isEmpty()` 的替代方式,例如: ```java if (imePackage != null && !imePackage.trim().isEmpty()) { // 处理逻辑 } ``` 这种方式还可以额外排除仅包含空白字符的情况。 - **Guava 或其他工具库**:如果项目引入了第三方库,如 Google Guava,则可以使用 `Strings.isNullOrEmpty()` 或类似函数来增强判断逻辑。 ### 注意事项 - **性能考量**:`TextUtils.isEmpty()` 性能良好,适用于频繁调用的场景。 - **线程安全**:该方法是无状态的,可以在多线程环境中安全使用[^2]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值