回答
T-Mobile的「我的帳戶」應用程序會這樣做,如果您連接到WiFi連接,它會告訴您他們的程序無法通過WiFi工作,然後詢問用戶是否要關閉WiFi連接。如果你選擇「否」,那麼應用程序退出,如果你選擇「是」,那麼應用程序關閉你的WiFi連接,然後繼續啓動。
我認爲這是一個很好的模型,它會確保您的應用程序不會在WiFi上運行,並允許用戶決定是否要關閉WiFi。對此模型的改進是在用戶從您的應用程序導航離開時將WiFi重新開啓。沒有測試過d下面的代碼,但它看起來像它應該工作(從here修改)
使用下面的權限,您的清單
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
,這裏是一些實際的代碼來打開WiFi /關閉
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);
}
}
如果你不想沿着這條路線走,看起來你可能會告訴手機你更喜歡使用移動數據網絡而不是WiFi網絡。
Android ConnectivityManager提供功能setNetworkPreference。這個功能沒有真正的記錄,因爲你可以告訴你是否點擊鏈接。我會仔細研究它,因爲定義的常量似乎暗示您可以將其設置爲TYPE_MOBILE或TYPE_WIFI,並且還有一個DEFAULT_NETWORK_PREFERENCE常量,它被定義爲0x00000001,它與TYPE_WIFI相同。因此,請嘗試通過調用
Context.getSystemService(Context.CONNECTIVITY_SERVICE);
訪問ConnectivityManager,然後嘗試使用setNetworkPreference()函數。
它似乎不需要清單中的任何權限,但它可能需要CHANGE_NETWORK_STATE權限或沿着這些行的東西。
如果你起訴setNetworkPreference功能它很可能是最好也設置網絡偏好回原來的值(從getNetworkPreference收到)
我希望這有助於。
雖然有用,但從@Rainbowbreeze得到的答案是正確的答案。 – Josh 2014-02-01 05:38:53
我認爲這是不可能從Java。如果連接到無線網絡,系統將關閉所有基於移動網絡的通信。我認爲你不能從你的程序開始3G連接。
感謝q如果移動用戶啓用都意味着3G和WiFi,那時候我的應用程序運行失敗,因爲它不斷跳到WiFi和3G到WiFi可以u pl給任何替代解決方案 – Aswan 2010-03-25 14:04:01
有沒有辦法解決這個問題。如果用戶有一個非常明顯的3G連接,她會一直得到網絡和鬆散的網絡連接。 您可以做的唯一的事情就是對您的服務器做小而頻繁的請求,並且不要試圖保持連接長時間打開。 然後以適當的方式處理網絡錯誤,可能會重試它或建議用戶稍後嘗試使用更穩定的連接。 – Janusz 2010-03-25 15:38:20
我很抱歉,但Android上的東西真的很糟糕。我測試了2個BSD插座綁定到Wi-Fi,另一個到3G IP地址。當Android切換到另一種網絡類型時,Android確實會阻塞一個套接字(不接收數據包)。如果使用connectedManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI,hostAddress);''''與connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,「enableHIPRI」);'''你有一個套接字,你綁定到另一個地址接收不對應的數據包 - 更糟糕。 – 2015-04-23 23:32:16
/**
* 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擎天柱測試,其他手機我不知道,因爲ConnectivityMananger的一些方法是供應商特定的。 閒置15-20秒後,移動網絡會自動斷開連接。
我不能滿足這個。這正是我所需要的,並且像魅力一樣工作而不需要改變任何東西。這是我在整個互聯網上爲這個問題找到的唯一很好的解決方案。 – Robber 2013-04-06 14:25:32
我的工作就像一個魅力一樣快。我必須定期(每隔30秒左右)調用startUsingNetworkFeature,否則即使在傳輸數據時也會斷開連接。有了這個解決方法,我還沒有遇到任何其他問題。謝謝! – Robber 2013-04-06 17:50:46
除了這個優秀的答案,如果有人想打開一個關機的數據連接,我會建議從這個答案添加一個調用方法: http://stackoverflow.com/a/11555457/2347363 可以在這行之前調用: 「for(int counter = 0; counter <30; counter ++)」 這樣,如果數據切換關閉,它也可以工作 – Antilope 2015-01-09 20:57:15
此應用程序激活3G和Wifi連接,優先選擇3G! 非常有用http://www.redrails.com.br/2012/02/wireless-analyzer-for-android/
使用連接管理器並根據需要設置網絡首選項。 好luk
例如: dataManager =(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE); dataManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE); dataManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
ConnectivityManager.setNetworkPreference()已接近廢棄。但更重要的是,如果在更改之前獲取NetWorkPreference(),它將返回ConnectivityManager.TYPE_MOBILE。在那裏設置沒有任何區別。至於HIPRI本身,它的工作方式非常奇怪。首先,它允許連接到所有主機,而不僅僅是通過路由明確請求的主機。其次,當您使用stopUsingFeature ...()調用將其關閉時,它不會被關閉,並且仍然處於活動狀態。第三,即使無線網絡可用,所有的應用程序都會使用它,這與文檔相矛盾。 – 2013-12-22 09:44:34
受此門票中的代碼的啓發,並使用它的一些部分,這裏是建立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;
}
}
這是我如何在需要時啓動/停止它。請注意,它也會鎖定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它已經請求的那些宿主,可以是用於其他主機(其路由請求)使用默認網絡(MOBILE或WIFI )。
- 打電話stopUsingNetworkFeature(),它會檢查 - 是否有任何其他應用程序正在使用此網絡,如果是,那麼它將忽略您的請求關閉此網絡功能。
- HIPRI網絡的主要目的之一就是 - 如果wifi在運行並且一個應用想要使用移動網絡(3G)到達特定的主機,它可以通過HIPRI網絡到達。
以下是適用於API 21+(棒棒糖,棉花糖..)的代碼。 我更喜歡使用OkHttp與Network.getSocketFactory(),但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();
}
}
});
}
OkHttp似乎沒有爲我工作(這很奇怪),但network.openURLConnection()做到了。 – user1691694 2017-01-03 05:23:27
- 1. 應用程序如果使用3G連接掛起(WiFi是好的)
- 2. 如何強制GPRS連接而不是3G或Wifi?
- 3. Android客戶端套接字隨機關閉,如果使用3G連接,而不是WiFi連接
- 4. 如何在我的Android應用程序中使用3G互聯網連接?
- 5. Android - 如何在可用WiFi時保持3g連接
- 6. Android應用程序工作正常,在3G,但不帶WIFI
- 7. 如何檢測移動連接是使用javascript的2G/3G/WIFI
- 8. 應用程序不與3G連接工作,但在wifi上工作正常
- 9. Android:3G到WIFI切換,而在應用程序的中間=丟失網絡連接
- 10. 阻斷3G連接Iphone應用程序
- 11. 使用Android應用程序的Wifi連接訪問
- 12. Android:通過應用程序使用Wifi連接
- 13. 應用程序通過wifi加載圖像,但不是3g
- 14. 強制應用程序通過wi-fi連接在WP7.5中使用3G連接
- 15. 如何從我的應用程序中激活wifi和3G
- 16. 使Android應用程序使用Wifi從非Android應用程序接收數據
- 17. 如何在Android應用程序中同時使用移動wifi和數據連接用於不同目的
- 18. 如何在Android應用程序中使用fb連接?
- 19. 使用Android的WIFI到WIFI連接性
- 20. Android應用程序不更新在WiFi
- 21. 當連接到adhoc wifi時使用3g(使用私有API)
- 22. 如果未連接到互聯網,請求用戶啓動WiFi或3G啓動Android應用程序
- 23. 如何找到是否iPhone設備連接到使用可達性3G/Wifi
- 24. 如何啓用數據連接而不是WIFI?
- 25. 如何檢查wifi/3g是否啓用?
- 26. 檢查Appcelerator Mobile應用程序中的網絡連接類型是2G,3G,4G還是WiFi?
- 27. 如何在連接URL之前檢測用戶是否擁有3G/Wifi?
- 28. 在Android應用程序中連接SQLite
- 29. Android應用程序如何使用3G/GPRS/EDGE
- 30. 如何知道設備連接到WiFi或3G,編程
爲什麼不打開無線連接首選項,讓用戶自己禁用wifi。相當侵擾性,但用戶在掌控之中。 – MrSnowflake 2010-03-25 15:00:25
我正在尋找一種方法來做到這一點,但我正在尋找「優先」(我認爲這將是正確的名稱),而不是「偏好」。感謝您的好問題和答案。 – 2011-12-03 13:37:06
@MsSnowflake如果您想要通過網絡接口分配負載,或者您信任一個接口上的敏感信息,並且希望通過可信通道和其他流量通過不可信通道路由敏感流量,或者您擔心其中一個接口更多很可能會在大量下載過程中退出,或者您只是希望爲用戶提供清晰細緻的應用程序特定權限,但您不希望打開* global *設置頁面來解決特定於應用程序的問題。 – 2014-06-11 17:10:54