yifeの日記

Supercalifragilisticexpialidocious

getSystemServiceをActivityでないclassで使う

Androidネタ。

ネットワークに通信するアプリを作成するときによく使うイディオムとして、通信を開始する前に、そもそも端末がネットワークに接続されているかどうかを調べることがある。

public Boolean isConnected(){
    ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
    if(networkInfo != null && networkInfo.isConnected()){
        return true;
    }else{
        return false;
    }
}


このメソッドがActivityの内部で実装されているときは、このままで問題ない。たとえばこんな感じ。

public class MainActivity extends Activity {
    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
    }
    
    private class MyNetworkTask extends AsyncTask<String, Void, String>{
        ...
    }
    
    public Boolean checkNetworkAvailable(){
        ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
        if(networkInfo != null && networkInfo.isConnected()){
            return true;
        }else{
            return false;
        }
    }
    
    public void readWebpage(View view){
        if(this.checkNetworkAvailable() != true){
            Toast.makeText(this, "No Network Connection", Toast.LENGTH_LONG).show();
            return;
        }
        MyNetworkTask task = new MyNetworkTask();
        task.execute(new String[]{ "http://www.google.com" });
    }

}


ところで、こういったActivityをたくさんつくっていると、checkNetworkAvailable()を何度も書くことになるから、この部分を外部クラスにまとめたくなる。

public class CheckNetworkAvailable {
	public Boolean isConnected(){
		ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
		if(networkInfo != null && networkInfo.isConnected()){
			return true;
		}else{
			return false;
		}
	}
}

ところが、このコードは動かない。getSystemService()がどこにも実装されていないからだ。
getSystemService()はActivityとServiceに実装されている。これらを継承することもできるが、ただのヘルパークラスをActivityやServiceとして登録するのは奇妙な感じがする。

この問題を解決するには、ActivityがCheckNetworkAvailableインスタンスを生成するときに自分自身を引数に渡してやり、CheckNetworkAvailable.isConnected()メソッド内でActivityインスタンスが持つgetSystemService()を呼んでやればよい。

ヘルパークラス側

public class CheckNetworkAvailable {
	Context context;
	
	public CheckNetworkAvailable(Context context){
		this.context = context;
	}
	
	public Boolean isConnected(){
		ConnectivityManager connManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
		if(networkInfo != null && networkInfo.isConnected()){
			return true;
		}else{
			return false;
		}
	}
}

Activity側

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    public void onClickButtonFetchWebpage(View v){
        CheckNetworkConnection checkNetworkConnection = new CheckNetworkConnection(this);
        ...
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

どっとはらい