如何在Android应用程序中使用3G连接而不是使用Wi-Fi?
如何在Android应用程序中使用3G连接而不是使用Wi-Fi?
我想连接一个3G连接,是否有任何示例代码连接到3G而不是Wi-Fi?
T-Mobile的“我的帐户”应用程序是这样做的,如果你连接到WiFi连接,它会告诉你他们的程序不能通过WiFi工作,然后询问用户是否要closuresWiFi连接。如果你select“没有“,那么应用程序退出,如果你select”是“,那么应用程序closures你的WiFi连接,然后继续启动。
我认为这是一个很好的模式,它将确保您的应用程序不会被WiFi运行,并允许用户决定是否要closuresWiFi。 这种模式的一个改进将是当用户从您的应用程序导航离开时,重新启动无线networking。
我还没有testing下面的代码,但它看起来应该工作(从这里修改)
在清单中使用以下权限
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
这里是一些实际的代码来打开/closures无线networking
private WifiManager wifiManager; @Override public void onCreate(Bundle icicle) { .................... wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); if(wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(false); } else { wifiManager.setWifiEnabled(true); } }
如果你不想走这条路,看起来你可能会告诉手机,你更喜欢使用移动数据networking,而不是无线networking。
Android ConnectivityManager提供了一个函数setNetworkPreference 。 这个function没有真正的文档,你可以告诉你是否点击链接。 我会打开它,虽然因为定义的常量似乎暗示可以将其设置为TYPE_MOBILE或TYPE_WIFI,并且还有一个DEFAULT_NETWORK_PREFERENCE常量以及被定义为0x00000001,这是与TYPE_WIFI相同。 所以试着通过调用来访问ConnectivityManager
Context.getSystemService(Context.CONNECTIVITY_SERVICE);
然后尝试使用setNetworkPreference()函数。
它似乎不需要清单中的任何权限,但它可能需要CHANGE_NETWORK_STATE权限或沿着这些行的东西。
如果你确实起诉了setNetworkPreference函数,最好还是将Network Preference设置回它的原始值(从getNetworkPreference接收)
我希望这有帮助。
/** * Enable mobile connection for a specific address * @param context a Context (application or activity) * @param address the address to enable * @return true for success, else false */ private boolean forceMobileConnectionForAddress(Context context, String address) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (null == connectivityManager) { Log.debug(TAG_LOG, "ConnectivityManager is null, cannot try to force a mobile connection"); return false; } //check if mobile connection is available and connected State state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); Log.debug(TAG_LOG, "TYPE_MOBILE_HIPRI network state: " + state); if (0 == state.compareTo(State.CONNECTED) || 0 == state.compareTo(State.CONNECTING)) { return true; } //activate mobile connection in addition to other connection already activated int resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI"); Log.debug(TAG_LOG, "startUsingNetworkFeature for enableHIPRI result: " + resultInt); //-1 means errors // 0 means already enabled // 1 means enabled // other values can be returned, because this method is vendor specific if (-1 == resultInt) { Log.error(TAG_LOG, "Wrong result of startUsingNetworkFeature, maybe problems"); return false; } if (0 == resultInt) { Log.debug(TAG_LOG, "No need to perform additional network settings"); return true; } //find the host name to route String hostName = StringUtil.extractAddressFromUrl(address); Log.debug(TAG_LOG, "Source address: " + address); Log.debug(TAG_LOG, "Destination host address to route: " + hostName); if (TextUtils.isEmpty(hostName)) hostName = address; //create a route for the specified address int hostAddress = lookupHost(hostName); if (-1 == hostAddress) { Log.error(TAG_LOG, "Wrong host address transformation, result was -1"); return false; } //wait some time needed to connection manager for waking up try { for (int counter=0; counter<30; counter++) { State checkState = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); if (0 == checkState.compareTo(State.CONNECTED)) break; Thread.sleep(1000); } } catch (InterruptedException e) { //nothing to do } boolean resultBool = connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress); Log.debug(TAG_LOG, "requestRouteToHost result: " + resultBool); if (!resultBool) Log.error(TAG_LOG, "Wrong requestRouteToHost result: expected true, but was false"); return resultBool; }
这个用于计算主机地址:
/** * This method extracts from address the hostname * @param url eg. http://some.where.com:8080/sync * @return some.where.com */ public static String extractAddressFromUrl(String url) { String urlToProcess = null; //find protocol int protocolEndIndex = url.indexOf("://"); if(protocolEndIndex>0) { urlToProcess = url.substring(protocolEndIndex + 3); } else { urlToProcess = url; } // If we have port number in the address we strip everything // after the port number int pos = urlToProcess.indexOf(':'); if (pos >= 0) { urlToProcess = urlToProcess.substring(0, pos); } // If we have resource location in the address then we strip // everything after the '/' pos = urlToProcess.indexOf('/'); if (pos >= 0) { urlToProcess = urlToProcess.substring(0, pos); } // If we have ? in the address then we strip // everything after the '?' pos = urlToProcess.indexOf('?'); if (pos >= 0) { urlToProcess = urlToProcess.substring(0, pos); } return urlToProcess; } /** * Transform host name in int value used by {@link ConnectivityManager.requestRouteToHost} * method * * @param hostname * @return -1 if the host doesn't exists, elsewhere its translation * to an integer */ private static int lookupHost(String hostname) { InetAddress inetAddress; try { inetAddress = InetAddress.getByName(hostname); } catch (UnknownHostException e) { return -1; } byte[] addrBytes; int addr; addrBytes = inetAddress.getAddress(); addr = ((addrBytes[3] & 0xff) << 24) | ((addrBytes[2] & 0xff) << 16) | ((addrBytes[1] & 0xff) << 8 ) | (addrBytes[0] & 0xff); return addr; }
并且必须将以下权限添加到AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
它只适用于Android 2.2及以上版本,在Nexus One和LG Optimus上testing,其他手机我不知道,因为ConnectivityMananger的某些方法是供应商特定的。 移动15-20秒后,移动networking自动断开。
我认为这是不可能的Java。 如果连接到无线networking,系统将closures所有基于移动networking的通信。 我认为你不能从你的程序启动3G连接。
这是API 21+(棒棒糖,棉花糖..)的代码。 我喜欢用Network.getSocketFactory()使用OkHttp,但Network.openURLConnection()也能正常工作。
private void doTest() { display("Requesting CELLULAR network connectivity..."); ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() { /** * Called when the framework connects and has declared a new network ready for use. * This callback may be called more than once if the {@link Network} that is * satisfying the request changes. * * This method will be called on non-UI thread, so beware not to use any UI updates directly. * * @param network The {@link Network} of the satisfying network. */ @Override public void onAvailable(final Network network) { display("Got available network: " + network.toString()); try { final InetAddress address = network.getByName("navalclash.com"); display("Resolved host2ip: " + address.getHostName() + " -> " + address.getHostAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } display("Do request test page from remote http server..."); if(okHttpClient == null) { okHttpClient = new OkHttpClient.Builder().socketFactory(network.getSocketFactory()).build(); } Request request = new Request.Builder() .url("http://navalclash.com") .build(); try (Response response = okHttpClient.newCall(request).execute()) { display("RESULT:\n" + response.body().string()); } catch (Exception ex) { ex.printStackTrace(); } } }); }
使用连接pipe理器并根据需要设置networking首选项。 好luk
例如:dataManager =(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE); dataManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
这个应用程序激活3G和Wifi连接,给3G的优惠! 非常有用http://www.redrails.com.br/2012/02/wireless-analyzer-for-android/
受到这张票的代码的启发,并使用它的一些部分,这里是build立hipri移动并保持运行的服务。
import java.net.InetAddress; import java.net.UnknownHostException; import java.util.concurrent.atomic.AtomicBoolean; import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo.State; import android.os.IBinder; import android.util.Log; public class HipriService extends Service { private AtomicBoolean enabledMobile = new AtomicBoolean(false); public boolean enableMobileConnection() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (null == cm) { Log.d(TAG, "ConnectivityManager is null, cannot try to force a mobile connection"); return false; } /* * Don't do anything if we are connecting. On the other hands re-new * connection if we are connected. */ State state = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); Log.d(TAG, "TYPE_MOBILE_HIPRI network state: " + state); if (0 == state.compareTo(State.CONNECTING)) return true; /* * Re-activate mobile connection in addition to other connection already * activated */ int resultInt = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI"); //Log.d(TAG, "startUsingNetworkFeature for enableHIPRI result: " + resultInt); //-1 means errors // 0 means already enabled // 1 means enabled // other values can be returned, because this method is vendor specific if (-1 == resultInt) { Log.e(TAG, "Wrong result of startUsingNetworkFeature, maybe problems"); return false; } if (0 == resultInt) { Log.d(TAG, "No need to perform additional network settings"); return true; } return requestRouteToHost(this, Uploader.ServerAddress); } private Thread pingerThread = null; private void startMobileConnection() { enabledMobile.set(true); pingerThread = new Thread(new Runnable() { @Override public void run() { while (enabledMobile.get()) { /* * Renew mobile connection. No routing setup is needed. This * should be moved to 3g monitoring service one day. */ enableMobileConnection(); try { Thread.sleep(1000); } catch (InterruptedException e) { // do nothing } } } }); pingerThread.start(); } private void stopMobileConnection() { enabledMobile.set(false); disableMobileConnection(); pingerThread.interrupt(); pingerThread = null; } public void disableMobileConnection() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI"); } public final static int inetAddressToInt(InetAddress inetAddress) { byte[] addrBytes; int addr; addrBytes = inetAddress.getAddress(); addr = ((addrBytes[3] & 0xff) << 24) | ((addrBytes[2] & 0xff) << 16) | ((addrBytes[1] & 0xff) << 8) | (addrBytes[0] & 0xff); return addr; } public final static InetAddress lookupHost(String hostname) { try { return InetAddress.getByName(hostname); } catch (UnknownHostException e) { return null; } } private boolean requestRouteToHost(Context context, String hostname) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (null == cm) { Log.d(TAG, "ConnectivityManager is null, cannot try to force a mobile connection"); return false; } /* Wait some time needed to connection manager for waking up */ try { for (int counter = 0; enabledMobile.get() && counter < 30; counter++) { State checkState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); Log.i(TAG, "Waiting for mobile data on. State " + checkState); if (0 == checkState.compareTo(State.CONNECTED)) break; Thread.sleep(1000); } } catch (InterruptedException e) { //nothing to do } if (!enabledMobile.get()) { Log.d(TAG, "Mobile data is turned off while waiting for routing."); return false; } State checkState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); if (0 != checkState.compareTo(State.CONNECTED)) { Log.e(TAG, "Mobile data is still turned off after 30 sec of waiting."); return false; } Log.i(TAG, "Adding routing for " + hostname); InetAddress inetAddress = lookupHost(hostname); if (inetAddress == null) { Log.e(TAG, "Failed to resolve " + hostname); return false; } int hostAddress = inetAddressToInt(inetAddress); boolean resultBool = cm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress); Log.d(TAG, "requestRouteToHost result: " + resultBool); if (!resultBool) Log.e(TAG, "Wrong requestRouteToHost result: expected true, but was false"); return resultBool; } @Override public void onCreate() { super.onCreate(); startMobileConnection(); } @Override public void onDestroy() { stopMobileConnection(); super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } }
这里是我如何开始/停止需要的时候。 请注意,它也locking在CPU和WiFi,以便它可以运行时,电话睡觉(仅屏幕)。 WiFi是需要的,因为我的应用程序是WiFi和移动连接之间的桥梁。 你可能不需要它。
public void startMobileData() { if (!enabledMobile.get()) { enabledMobile.set(true); WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "Wifi Wakelock"); wifiLock.acquire(); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); partialLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "3G Wakelock"); partialLock.acquire(); startService(new Intent(this, HipriService.class)); } } public void stopMobileData() { if (enabledMobile.get()) { enabledMobile.set(false); Log.i(TAG, "Disabled mobile data"); stopService(new Intent(this, HipriService.class)); if (partialLock != null) { partialLock.release(); partialLock = null; } if (wifiLock != null) { wifiLock.release(); wifiLock = null; } } }
不要忘记为清单文件添加服务。
@umka
- 我认为,应用程序只能通过它请求的HIPRI到达那些主机,可能是其他主机(其路由未被请求)正在使用默认networking(MOBILE或WIFI)。
- 在调用stopUsingNetworkFeature()时 ,它会检查是否有任何其他应用程序正在使用此networking,如果是的话,那么它将忽略您的请求closures此networkingfunction。
- HIPRInetworking的主要目的之一就是 – 如果WIFI打开,一个应用程序想要使用移动networking(3G)到达特定的主机,它可以通过HIPRInetworking到达。