Java tutorial
/* * Copyright (c) 2016 ? (OHMAE Ryosuke) * * This software is released under the MIT License. * http://opensource.org/licenses/MIT */ package net.mm2d.dmsexplorer; import android.app.ActivityOptions; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.transition.Slide; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import net.mm2d.android.cds.MediaServer; import net.mm2d.android.cds.MsControlPoint; import net.mm2d.android.cds.MsControlPoint.MsDiscoveryListener; import net.mm2d.android.widget.DividerItemDecoration; import net.mm2d.dmsexplorer.ServerListAdapter.OnItemClickListener; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.List; /** * MediaServer?????Activity * * <p>???Activity * * @author <a href="mailto:ryo@mm2d.net">?(OHMAE Ryosuke)</a> */ public class ServerListActivity extends AppCompatActivity { private static final String TAG = "ServerListActivity"; private boolean mTwoPane; private boolean mNetworkAvailable; private Handler mHandler; private SearchThread mSearchThread; private final DataHolder mDataHolder = DataHolder.getInstance(); private final MsControlPoint mMsControlPoint = mDataHolder.getMsControlPoint(); private MediaServer mSelectedServer; private ServerDetailFragment mServerDetailFragment; private ServerListAdapter mServerListAdapter; private ConnectivityManager mConnectivityManager; private SwipeRefreshLayout mSwipeRefreshLayout; private final BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final boolean available = hasAvailableNetwork(); if (mNetworkAvailable != available) { synchronized (mMsControlPoint) { if (available) { mMsControlPoint.initialize(getWifiInterface()); mMsControlPoint.start(); } else { mMsControlPoint.stop(); mMsControlPoint.terminate(); showToast(R.string.no_available_network); mServerListAdapter.clear(); mServerListAdapter.notifyDataSetChanged(); } } mNetworkAvailable = available; } } }; private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() { @Override public void onItemClick(final @NonNull View v, final @NonNull View accent, final int position, final @NonNull MediaServer server) { if (mTwoPane) { if (mSelectedServer != null && mSelectedServer.equals(server)) { return; } mServerDetailFragment = ServerDetailFragment.newInstance(server.getUdn()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mServerDetailFragment.setEnterTransition(new Slide(Gravity.START)); } getSupportFragmentManager().beginTransaction() .replace(R.id.server_detail_container, mServerDetailFragment).commit(); mServerListAdapter.setSelection(position); mSelectedServer = server; } else { final Context context = v.getContext(); final Intent intent = ServerDetailActivity.makeIntent(context, server.getUdn()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { startActivity(intent, ActivityOptions .makeSceneTransitionAnimation(ServerListActivity.this, accent, "share").toBundle()); } else { startActivity(intent); } } } }; private boolean hasAvailableNetwork() { final NetworkInfo ni = mConnectivityManager.getActiveNetworkInfo(); return ni != null && ni.isConnected() && (ni.getType() == ConnectivityManager.TYPE_WIFI || ni.getType() == ConnectivityManager.TYPE_ETHERNET); } // TODO: ?WIFIEther private Collection<NetworkInterface> getWifiInterface() { final NetworkInfo ni = mConnectivityManager.getActiveNetworkInfo(); if (ni == null || !ni.isConnected() || ni.getType() != ConnectivityManager.TYPE_WIFI) { return null; } final InetAddress address = getWifiInetAddress(); if (address == null) { return null; } final Enumeration<NetworkInterface> nis; try { nis = NetworkInterface.getNetworkInterfaces(); } catch (final SocketException e) { return null; } while (nis.hasMoreElements()) { final NetworkInterface nif = nis.nextElement(); try { if (nif.isLoopback() || nif.isPointToPoint() || nif.isVirtual() || !nif.isUp()) { continue; } final List<InterfaceAddress> ifas = nif.getInterfaceAddresses(); for (final InterfaceAddress a : ifas) { if (a.getAddress().equals(address)) { final Collection<NetworkInterface> c = new ArrayList<>(); c.add(nif); return c; } } } catch (final SocketException ignored) { } } return null; } private InetAddress getWifiInetAddress() { final WifiInfo wi = ((WifiManager) getSystemService(WIFI_SERVICE)).getConnectionInfo(); if (wi == null) { return null; } try { return InetAddress.getByAddress(intToByteArray(wi.getIpAddress())); } catch (final UnknownHostException ignored) { } return null; } private byte[] intToByteArray(int ip) { final byte[] array = new byte[4]; array[0] = (byte) (ip & 0xff); ip >>= 8; array[1] = (byte) (ip & 0xff); ip >>= 8; array[2] = (byte) (ip & 0xff); ip >>= 8; array[3] = (byte) (ip & 0xff); return array; } private final MsDiscoveryListener mDiscoveryListener = new MsDiscoveryListener() { @Override public void onDiscover(@NonNull final MediaServer server) { mHandler.post(() -> onDiscoverServer(server)); } @Override public void onLost(@NonNull final MediaServer server) { mHandler.post(() -> onLostServer(server)); } }; private void onDiscoverServer(MediaServer server) { mSwipeRefreshLayout.setRefreshing(false); if (mMsControlPoint.getMediaServerListSize() != mServerListAdapter.getItemCount() + 1) { mServerListAdapter.clear(); mServerListAdapter.addAll(mMsControlPoint.getMediaServerList()); mServerListAdapter.notifyDataSetChanged(); } else { final int position = mServerListAdapter.add(server); mServerListAdapter.notifyItemInserted(position); } } private void onLostServer(MediaServer server) { final int position = mServerListAdapter.remove(server); if (position >= 0) { if (mMsControlPoint.getMediaServerListSize() == mServerListAdapter.getItemCount()) { mServerListAdapter.notifyItemRemoved(position); } else { mServerListAdapter.clear(); mServerListAdapter.addAll(mMsControlPoint.getMediaServerList()); mServerListAdapter.notifyDataSetChanged(); } } if (mTwoPane && server.equals(mSelectedServer)) { if (mServerDetailFragment != null) { getSupportFragmentManager().beginTransaction().remove(mServerDetailFragment).commit(); mServerDetailFragment = null; mServerListAdapter.setSelection(-1); mSelectedServer = null; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.defaultStatusBar)); } setContentView(R.layout.act_server_list); mHandler = new Handler(); mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); assert toolbar != null; setSupportActionBar(toolbar); toolbar.setTitle(getTitle()); mMsControlPoint.setMsDiscoveryListener(mDiscoveryListener); mServerListAdapter = new ServerListAdapter(this, mMsControlPoint.getMediaServerList()); mServerListAdapter.setOnItemClickListener(mOnItemClickListener); mNetworkAvailable = hasAvailableNetwork(); synchronized (mMsControlPoint) { if (mNetworkAvailable) { if (savedInstanceState == null) { mMsControlPoint.initialize(getWifiInterface()); mMsControlPoint.start(); } } else { mMsControlPoint.terminate(); } } registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefresh); assert mSwipeRefreshLayout != null; mSwipeRefreshLayout.setColorSchemeResources(R.color.progress1, R.color.progress2, R.color.progress3, R.color.progress4); mSwipeRefreshLayout.setRefreshing(mServerListAdapter.getItemCount() == 0); mSwipeRefreshLayout.setOnRefreshListener(() -> { if (!hasAvailableNetwork()) { return; } synchronized (mMsControlPoint) { mMsControlPoint.stop(); mMsControlPoint.terminate(); mServerListAdapter.clear(); mServerListAdapter.notifyDataSetChanged(); mMsControlPoint.initialize(getWifiInterface()); mMsControlPoint.start(); } }); final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.server_list); assert recyclerView != null; recyclerView.setAdapter(mServerListAdapter); recyclerView.addItemDecoration(new DividerItemDecoration(this)); if (findViewById(R.id.server_detail_container) != null) { mTwoPane = true; } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mConnectivityReceiver); if (isFinishing()) { synchronized (mMsControlPoint) { mMsControlPoint.setMsDiscoveryListener(null); mMsControlPoint.terminate(); } } } @Override protected void onResume() { super.onResume(); mSearchThread = new SearchThread(); mSearchThread.start(); if (!hasAvailableNetwork()) { showToast(R.string.no_available_network); } } @Override protected void onPause() { super.onPause(); mSearchThread.shutdownRequest(); mSearchThread = null; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { final int id = item.getItemId(); if (id == R.id.action_settings) { startActivity(SettingsActivity.makeIntent(this)); return true; } return super.onOptionsItemSelected(item); } private void showToast(int resId) { Toast.makeText(this, resId, Toast.LENGTH_LONG).show(); } private class SearchThread extends Thread { public void shutdownRequest() { interrupt(); } @Override public void run() { try { while (!interrupted()) { synchronized (mMsControlPoint) { if (mMsControlPoint.isInitialized()) { mMsControlPoint.search(); } } Thread.sleep(5000); } } catch (final InterruptedException ignored) { } } } }