Ağ kullanımını yönetme

Bu derste ayrıntılı denetime sahip uygulamaların nasıl yazılacağı açıklanmaktadır. daha fazla dikkat etmesi gerekir. Uygulamanız çok sayıda ağ işlemleri için, ağ operasyonlarını denetlemek üzere kullanıcıların uygulamanızın veri alışkanlıkları (ör. uygulamanızın verileri ne sıklıkta senkronize ettiği, Yükleme/indirme işlemlerini sadece kablosuz bağlantıda yap. Dolaşımdayken veri kullanma ya da vb. Bu kontroller kullanıcılara sunulduğunda kullanıcıların Uygulamanızın arka plan verilerine erişimini devre dışı bırakmak ve çünkü uygulamanızın kullandığı veri miktarını hassas bir şekilde kontrol edebilirler.

Uygulamanızın ağ kullanımı hakkında daha fazla bilgi edinmek için görmek için Web Yöneticisi Araçları'nda uygulamalar ve Ağ trafiğini inceleme profil aracı. indirme işlemlerinin ve ağın pil ömrü etkisini en aza indiren uygulamalar yazma Pil ömrünü optimize etme ve Pili bitirmeden verileri aktarın.

Daha fazla bilgi edinmek için NetworkConnect örnek bölümüne bakın.

Cihazların ağ bağlantısını kontrol etme

Bir cihazda çeşitli türlerde ağ bağlantıları olabilir. Bu derste Kablosuz veya mobil ağ bağlantısı kullanarak. olası ağ türlerine bakın, ConnectivityManager.

Kablosuz bağlantı genellikle daha hızlıdır. Ayrıca, mobil veri genellikle sayaçlı olur. Bu da, Pahalı. Uygulamalar için yaygın olarak kullanılan bir strateji, büyük verileri yalnızca bir kablosuz ağ kullanılabilir durumda olduğundan emin olun.

Ağ işlemleri gerçekleştirmeden önce ağ bağlantısı. Diğer sebeplerin yanı sıra bu, uygulamanızın istemeden yanlış radyoyu kullanmaya başladı. Ağ bağlantısı yoksa olumlu yanıt vermesi gerekir. Ağ bağlantısını kontrol etmek için genellikle aşağıdaki sınıfları kullanır:

  • ConnectivityManager: Ağın durumuyla ilgili sorguları yanıtlar yardımcı olur. Ayrıca, ağ bağlantısı olduğunda uygulamaları bilgilendirir anlamına gelir.
  • NetworkInfo: Bir öğenin durumunu tanımlar ağ arayüzü (şu anda Mobil veya Kablosuz).

Bu kod snippet'i, kablosuz ağ ve mobil ağ bağlantısını test eder. Bir projeyi Bu ağ arayüzlerinin kullanılabilir olup olmadığı (diğer bir deyişle, bağlantı olanağı sağlanabiliyor) ve/veya bağlı (yani ağ bağlantısı bağlantı mevcut olup olmadığı ve yuvaların kurulması ve veri aktarımı mümkünse):

Kotlin

private const val DEBUG_TAG = "NetworkStatusExample"
...
val connMgr = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
var isWifiConn: Boolean = false
var isMobileConn: Boolean = false
connMgr.allNetworks.forEach { network ->
    connMgr.getNetworkInfo(network).apply {
        if (type == ConnectivityManager.TYPE_WIFI) {
            isWifiConn = isWifiConn or isConnected
        }
        if (type == ConnectivityManager.TYPE_MOBILE) {
            isMobileConn = isMobileConn or isConnected
        }
    }
}
Log.d(DEBUG_TAG, "Wifi connected: $isWifiConn")
Log.d(DEBUG_TAG, "Mobile connected: $isMobileConn")

Java

private static final String DEBUG_TAG = "NetworkStatusExample";
...
ConnectivityManager connMgr =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isWifiConn = false;
boolean isMobileConn = false;
for (Network network : connMgr.getAllNetworks()) {
    NetworkInfo networkInfo = connMgr.getNetworkInfo(network);
    if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
        isWifiConn |= networkInfo.isConnected();
    }
    if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
        isMobileConn |= networkInfo.isConnected();
    }
}
Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);
Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);

Kararlarınızı, bir ağın "kullanılabilir" olup olmadığına dayandırmamanız gerektiğini unutmayın. Siz her zaman Şu tarihten önce isConnected(): isConnected() stabilite gibi durumlarda ağ işlemleri gerçekleştiriyor, çünkü mobil ağlar, uçak modu ve kısıtlanmış arka plan verileri.

Bir ağ arayüzünün kullanılabilir olup olmadığını kontrol etmenin daha kısa ve öz anlatacağım. Yöntem getActiveNetworkInfo() bir NetworkInfo örneği döndürür bulabildiği ilk bağlı ağ arayüzünü temsil eder veya varsa null arayüzlerin hiçbiri bağlı değil (yani, kullanılabilir):

Kotlin

fun isOnline(): Boolean {
    val connMgr = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo: NetworkInfo? = connMgr.activeNetworkInfo
    return networkInfo?.isConnected == true
}

Java

public boolean isOnline() {
    ConnectivityManager connMgr = (ConnectivityManager)
            getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    return (networkInfo != null && networkInfo.isConnected());
}

Daha ayrıntılı durumu sorgulamak için NetworkInfo.DetailedState Ancak bu nadiren gerekir.

Ağ kullanımını yönetme

Kullanıcılara üzerinde açık bir şekilde kontrol sahibi olma imkanı sunan bir tercihler etkinliği ağ kaynaklarını nasıl kullandığını gösterir. Örnek:

  • Kullanıcıların video yüklemesine yalnızca cihaz bir Kablosuz ağ.
  • Ağ gibi belirli ölçütlere bağlı olarak senkronize edebilirsiniz (veya yapmayabilirsiniz) uygunluk durumu, zaman aralığı vb.

Ağ erişimini destekleyen ve ağ kullanımını yöneten bir uygulama yazmak için manifesto doğru izinlere ve intent filtrelerine sahip olmalıdır.

  • Bu bölümün ilerleyen kısımlarında alıntılanan manifest şunları içerir: izinler:
  • Şunun için intent filtresini tanımlayabilirsiniz: ACTION_MANAGE_NETWORK_USAGE uygulamanızın, farklı seçenekler sunan bir etkinlik tanımladığını seçenekleri vardır. ACTION_MANAGE_NETWORK_USAGE, ayarları gösterir ağ veri kullanımını yönetmek için kullanılan bir araçtır. Uygulamanız Kullanıcıların ağ kullanımını kontrol etmesine olanak tanıyan bir ayar etkinliğine sahipse bu intent filtresini o etkinlik için bildirin.

Örnek uygulamada bu işlem sınıf tarafından gerçekleştirilir SettingsActivity, kullanıcıların ne zaman ne zaman yapacağına karar vermesine olanak tanıyan bir tercihler kullanıcı arayüzü görüntüler. bir özet akışı indirin.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.networkusage"
    ...>

    <uses-sdk android:minSdkVersion="4"
           android:targetSdkVersion="14" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        ...>
        ...
        <activity android:label="SettingsActivity" android:name=".SettingsActivity">
             <intent-filter>
                <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
                <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
        </activity>
    </application>
</manifest>

Hassas kullanıcı verileriyle işleyen ve Android 11 ve daha yüksek olanlar işlem başına ağ erişimi verebilir. Bunun için işlemler için ağ erişimine izin verildiğini ve Veri yükleme

Uygulamanızın yanlışlıkla veri yüklemesini engelleyeceği garanti edilmese de uygulamanızdaki hataların, uygulamanızın veri sızıntısı olabilir.

Aşağıda, işlem başına işlev:

<processes>
    <process />
    <deny-permission android:name="android.permission.INTERNET" />
    <process android:process=":withoutnet1" />
    <process android:process="com.android.cts.useprocess.withnet1">
        <allow-permission android:name="android.permission.INTERNET" />
    </process>
    <allow-permission android:name="android.permission.INTERNET" />
    <process android:process=":withoutnet2">
        <deny-permission android:name="android.permission.INTERNET" />
    </process>
    <process android:process="com.android.cts.useprocess.withnet2" />
</processes>

Tercih etkinliği uygulama

Bu konunun önceki manifest alıntısında görebileceğiniz üzere örnek uygulamanın SettingsActivity etkinliği, şunun için bir intent filtresine sahip: ACTION_MANAGE_NETWORK_USAGE işlem. SettingsActivity, şunun bir alt sınıfıdır: PreferenceActivity Google kullanıcıların istedikleri seçenekleri belirlemelerine olanak tanıyan bir tercihler ekranı (Şekil 1'de gösterilmektedir) takip etmek için:

  • Her XML özet akışı girişi için özetlerin mi yoksa her giriş için yalnızca bir bağlantının mı görüntüleneceğini belirtir.
  • XML feed'inin herhangi bir ağ bağlantısı varsa mı yoksa yalnızca kablosuz bağlantı varsa mı indirileceği kullanılabilir.

Tercihler paneli Ağ tercihi ayarlama

Şekil 1. Tercihler etkinliği.

İşte SettingsActivity. Şunun için geçerli olduğunu unutmayın: OnSharedPreferenceChangeListener. Kullanıcı bir tercihi değiştirdiğinde onSharedPreferenceChanged() refreshDisplay değerini doğru olarak ayarlar. Bu, kullanıcı ana etkinliğe döner:

Kotlin

class SettingsActivity : PreferenceActivity(), OnSharedPreferenceChangeListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Loads the XML preferences file
        addPreferencesFromResource(R.xml.preferences)
    }

    override fun onResume() {
        super.onResume()

        // Registers a listener whenever a key changes
        preferenceScreen?.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
    }

    override fun onPause() {
        super.onPause()

        // Unregisters the listener set in onResume().
        // It's best practice to unregister listeners when your app isn't using them to cut down on
        // unnecessary system overhead. You do this in onPause().
        preferenceScreen?.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)
    }

    // When the user changes the preferences selection,
    // onSharedPreferenceChanged() restarts the main activity as a new
    // task. Sets the refreshDisplay flag to "true" to indicate that
    // the main activity should update its display.
    // The main activity queries the PreferenceManager to get the latest settings.

    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
        // Sets refreshDisplay to true so that when the user returns to the main
        // activity, the display refreshes to reflect the new settings.
        NetworkActivity.refreshDisplay = true
    }
}

Java

public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Loads the XML preferences file
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Registers a listener whenever a key changes
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();

       // Unregisters the listener set in onResume().
       // It's best practice to unregister listeners when your app isn't using them to cut down on
       // unnecessary system overhead. You do this in onPause().
       getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }

    // When the user changes the preferences selection,
    // onSharedPreferenceChanged() restarts the main activity as a new
    // task. Sets the refreshDisplay flag to "true" to indicate that
    // the main activity should update its display.
    // The main activity queries the PreferenceManager to get the latest settings.

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        // Sets refreshDisplay to true so that when the user returns to the main
        // activity, the display refreshes to reflect the new settings.
        NetworkActivity.refreshDisplay = true;
    }
}

Tercih değişikliklerine yanıt verme

Kullanıcı, ayarlar ekranında tercihlerini değiştirdiğinde, genelde olumsuz sonuçlar doğurabilir. Bu snippet'te, uygulama tercihler ayarlarını onStart() bölümünde bulabilirsiniz. ayar ile cihazın ağ bağlantısı (örneğin, ayar "Wi-Fi" ve bağlantısı varsa) uygulama, feed'i indirir ve sayfayı yeniler. görüntüleyin.

Kotlin

class NetworkActivity : Activity() {

    // The BroadcastReceiver that tracks network connectivity changes.
    private lateinit var receiver: NetworkReceiver

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Registers BroadcastReceiver to track network connection changes.
        val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        receiver = NetworkReceiver()
        this.registerReceiver(receiver, filter)
    }

    public override fun onDestroy() {
        super.onDestroy()
        // Unregisters BroadcastReceiver when app is destroyed.
        this.unregisterReceiver(receiver)
    }

    // Refreshes the display if the network connection and the
    // pref settings allow it.

    public override fun onStart() {
        super.onStart()

        // Gets the user's network preference settings
        val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)

        // Retrieves a string value for the preferences. The second parameter
        // is the default value to use if a preference value is not found.
        sPref = sharedPrefs.getString("listPref", "Wi-Fi")

        updateConnectedFlags()

        if (refreshDisplay) {
            loadPage()
        }
    }

    // Checks the network connection and sets the wifiConnected and mobileConnected
    // variables accordingly.
    fun updateConnectedFlags() {
        val connMgr = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

        val activeInfo: NetworkInfo? = connMgr.activeNetworkInfo
        if (activeInfo?.isConnected == true) {
            wifiConnected = activeInfo.type == ConnectivityManager.TYPE_WIFI
            mobileConnected = activeInfo.type == ConnectivityManager.TYPE_MOBILE
        } else {
            wifiConnected = false
            mobileConnected = false
        }
    }

    // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
    fun loadPage() {
        if (sPref == ANY && (wifiConnected || mobileConnected) || sPref == WIFI && wifiConnected) {
            // AsyncTask subclass
            DownloadXmlTask().execute(URL)
        } else {
            showErrorPage()
        }
    }

    companion object {

        const val WIFI = "Wi-Fi"
        const val ANY = "Any"
        const val SO_URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort;=newest"

        // Whether there is a Wi-Fi connection.
        private var wifiConnected = false
        // Whether there is a mobile connection.
        private var mobileConnected = false
        // Whether the display should be refreshed.
        var refreshDisplay = true

        // The user's current network preference setting.
        var sPref: String? = null
    }
...

}

Java

public class NetworkActivity extends Activity {
    public static final String WIFI = "Wi-Fi";
    public static final String ANY = "Any";
    private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort;=newest";

    // Whether there is a Wi-Fi connection.
    private static boolean wifiConnected = false;
    // Whether there is a mobile connection.
    private static boolean mobileConnected = false;
    // Whether the display should be refreshed.
    public static boolean refreshDisplay = true;

    // The user's current network preference setting.
    public static String sPref = null;

    // The BroadcastReceiver that tracks network connectivity changes.
    private NetworkReceiver receiver = new NetworkReceiver();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Registers BroadcastReceiver to track network connection changes.
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        receiver = new NetworkReceiver();
        this.registerReceiver(receiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Unregisters BroadcastReceiver when app is destroyed.
        if (receiver != null) {
            this.unregisterReceiver(receiver);
        }
    }

    // Refreshes the display if the network connection and the
    // pref settings allow it.

    @Override
    public void onStart () {
        super.onStart();

        // Gets the user's network preference settings
        SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);

        // Retrieves a string value for the preferences. The second parameter
        // is the default value to use if a preference value is not found.
        sPref = sharedPrefs.getString("listPref", "Wi-Fi");

        updateConnectedFlags();

        if(refreshDisplay){
            loadPage();
        }
    }

    // Checks the network connection and sets the wifiConnected and mobileConnected
    // variables accordingly.
    public void updateConnectedFlags() {
        ConnectivityManager connMgr = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
        if (activeInfo != null && activeInfo.isConnected()) {
            wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
            mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
        } else {
            wifiConnected = false;
            mobileConnected = false;
        }
    }

    // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
    public void loadPage() {
        if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
                || ((sPref.equals(WIFI)) && (wifiConnected))) {
            // AsyncTask subclass
            new DownloadXmlTask().execute(URL);
        } else {
            showErrorPage();
        }
    }
...

}

Bağlantı değişikliklerini algıla

Yapbozun son parçası, BroadcastReceiver alt sınıfı, NetworkReceiver. Cihazın ağ bağlantısı değiştiğinde, NetworkReceiver aksiyona müdahale ediyor CONNECTIVITY_ACTION, ağ bağlantısı durumunun ne olduğunu belirler ve işaretleri ayarlar wifiConnected ve mobileConnected değerlerini doğru/yanlış olarak ayarlayın. Sonuç: geri döndüğünde yalnızca Android'e gidip en yeni feed'i seçin ve NetworkActivity.refreshDisplay olarak ayarlanmışsa ekranı güncelleyin true.

Gereksiz bir şekilde çağrılan bir BroadcastReceiver kurulumu kontrol edin. Örnek uygulama BroadcastReceiver verilerini kaydeder NetworkReceiver inç onCreate(), ve onDestroy(). Bu daha fazla manifest dosyasında <receiver> tanımlamaktan daha basittir. Google Takvim widget'ını manifest dosyasında bir <receiver> bildirirseniz uygulamanızı her an uyandırabilir birkaç haftadır yayınlamamış olsanız bile. Kaydolarak ve kaydınızı iptal ederek NetworkReceiver ana etkinlik içinde bulunursa uygulamanın kullanıcı uygulamadan ayrıldıktan sonra uyanık kalır. Bir Manifest dosyasında <receiver> var ve bunun tam olarak nerede ihtiyacınız olduğunu biliyorsanız kullanabilir setComponentEnabledSetting() ve gerektiği şekilde devre dışı bırakın.

NetworkReceiver:

Kotlin

class NetworkReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        val conn = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val networkInfo: NetworkInfo? = conn.activeNetworkInfo

        // Checks the user prefs and the network connection. Based on the result, decides whether
        // to refresh the display or keep the current display.
        // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
        if (WIFI == sPref && networkInfo?.type == ConnectivityManager.TYPE_WIFI) {
            // If device has its Wi-Fi connection, sets refreshDisplay
            // to true. This causes the display to be refreshed when the user
            // returns to the app.
            refreshDisplay = true
            Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show()

            // If the setting is ANY network and there is a network connection
            // (which by process of elimination would be mobile), sets refreshDisplay to true.
        } else if (ANY == sPref && networkInfo != null) {
            refreshDisplay = true

            // Otherwise, the app can't download content--either because there is no network
            // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
            // is no Wi-Fi connection.
            // Sets refreshDisplay to false.
        } else {
            refreshDisplay = false
            Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show()
        }
    }
}

Java

public class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager conn =  (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = conn.getActiveNetworkInfo();

        // Checks the user prefs and the network connection. Based on the result, decides whether
        // to refresh the display or keep the current display.
        // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
        if (WIFI.equals(sPref) && networkInfo != null
            && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            // If device has its Wi-Fi connection, sets refreshDisplay
            // to true. This causes the display to be refreshed when the user
            // returns to the app.
            refreshDisplay = true;
            Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();

        // If the setting is ANY network and there is a network connection
        // (which by process of elimination would be mobile), sets refreshDisplay to true.
        } else if (ANY.equals(sPref) && networkInfo != null) {
            refreshDisplay = true;

        // Otherwise, the app can't download content--either because there is no network
        // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
        // is no Wi-Fi connection.
        // Sets refreshDisplay to false.
        } else {
            refreshDisplay = false;
            Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
        }
    }
}