Category Archives: Java

この記事では、前回の記事で取り込んだエクセルのデータをプログラミング時に扱いやすくするコードについて解説します。

手順としては、

  1. 1行分の情報をまとめておくクラスをつくる
  2. ↑のクラスをまとめるクラス配列をコンストラクタで生成する
  3. クラス配列から欲しいデータを出し入れ

のようにやっていきます。

1.1行分の情報をまとめておくModelCharaクラスを作る

ナンバー、名前、年齢、性別、備考をまとめて1人分とするクラスをつくります。

ここでの変数を増やすことで、さらに多くの情報を取り込むことも可能です。

[ModelChara.java]

public class ModelChara {
	int		id		= 0;
	String	name	= "";
	int		age		= 0;
	boolean	sex		= true;
	String	memo	= "";

	public ModelChara(int id, String name, int age, boolean sex, String memo) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.memo = memo;
	}

	public int getID(){ return id; }
	public String getName(){ return name; }
	public int getAge(){ return age; }
	public boolean getSex(){ return sex; }
	public String getMemo(){ return memo; }
}

クラスを生成する際にコンストラクタで変数を格納していきます。

下の方のメソッドは、実際にデータを取り出す時に使います。

2.クラス配列をコンストラクタで生成する

すでに前回の記事で画像が出ていますが、1.のクラスを継承したクラス配列を生成します。

このファイルのコンストラクタで、エクセルから変換したデータを取り込むことになります。

ですので、エクセルで関数を使ってセルの内容をまとめるときには、このような完成形をイメージしてから結合しないといけません。

[CharaData.java]

public class CharaData {
	private ArrayList<ModelChara> chara_data = new ArrayList<ModelChara>();

	//コンストラクタにて情報を格納
	public CharaData() {
		chara_data.add(new ModelChara(1, "波平", 54, true, "1本だけ"));
		chara_data.add(new ModelChara(2, "フネ", 50, false, ""));
		chara_data.add(new ModelChara(3, "マスオ", 28, true, "早稲田大学商学部"));
		chara_data.add(new ModelChara(4, "サザエ", 24, false, "老けすぎではないか"));
		chara_data.add(new ModelChara(5, "カツオ", 11, true, "発想(企画力)\n話術(営業力)\n体育会系(野球ばっかしてる)\n将来は良い営業マン"));
		chara_data.add(new ModelChara(6, "ワカメ", 9, false, "パンツ"));
		chara_data.add(new ModelChara(7, "タラヲ", 3, true, ""));
		chara_data.add(new ModelChara(8, "タマ", 9, true, "メスだと思ってた……"));
	}

	public ArrayList<ModelChara> getData() {
		return this.chara_data;
	}
}

こちらのファイルでも、1.と同じく、getData()メソッドは、クラス配列を取り出すのに必要なものです。

3.Activitiyでクラス配列から欲しいデータを出し入れ

さて、Activityで実際にデータをやりとりするときは下記のようにします。

[SampleActivity.java]

<pre>//キャラデータ読み込み
CharaData class_chara = new CharaData();
ArrayList<ModelChara> chara_data = class_chara.getData();

//マスオの年齢を取得したいとき
int masuo_age = chara_data.get(2).getAge();
//タマの名前を取得したいとき
String cat_name = chara_data.get(7).getName();

1.と2.の手順は一件面倒なように思えますが、複数のActivityで何度も繰り返しデータを出し入れする場合には、ファイルを分けて管理するのが簡単です!

実際に使うときには、クラス配列なのでchara_dataをListViewに読み込ませていたりします。クリックした行の番号をchara_data.get(○○)の添え字として渡したり、とか。

エンジニアではない人とドキュメントを受け渡しすると、エクセルが使われることが非常に多いので、こういうやり方を覚えておくと便利ですよ!

Androidエンジニアのみなさんこんにちは!

突然ですが、みなさんはこういうドキュメントを渡されたことありませんか?

1

エクセルに記入されたデータをもとに、アプリに内容を反映していく、よくあるパターンだと思います。

エンジニアとしては、こういうint型String型が入り混じった複数のデータは、どうやって取り込むか悩ましいものです。

人によって色々やり方はあるでしょうが、普段私がやっているやり方を解説しようと思います。

1.エクセルの関数で横一列でまとめる

まず、エクセルのCONCATENATE()関数で、複数のセルの内容を結合させた文字列をつくります。

空白のセルで「=CONCATENATE( ○○ & △△ & □□ &……)」と入力すると、○○と△△と□□が結合されます。

○○、△△、□□にはそれぞれ、セル番号(A5、B3など)を入れたり、「” (ダブルクオーテーション)」で囲って任意の文字列を入れます。

例えば「=CONCATENATE( A1 & “←セルA1の内容 セルB2の内容→” & B2)」と入力すると、「○○←セルA1の内容 セルB2の内容→□□」と表示されます。

これを応用して、

=CONCATENATE(   “chara_data.add(new ModelChara(” & B3 & “, ” & “””” & C3 & “””” & “, ” & D3 & “, ” & “””” & E3 & “””” & “, ” & “””” & F3 & “””” & “));”   )

と入れます。

2

セルの位置や、前後に入れる文字列は内容によって違ってくると思います。

注意してほしいのは、「”(ダブルクオーテーション)」を文字としてそのまま結合したい場合は、「””””」と4つかたまりで入力しなくてはいけない点です。

さて、上記の関数を実行すると↓のような文字列に結合されます。

3

なんだかこのままEclipseにコピペできそうな形になりましたね!

2.全てのデータに関数を適用する

ここからはExcelの使い方の勉強です。

1.の工程で出来た1行の関数式を、そのまま全てのデータに適用したいですよね?

そういうときも下記の要領で簡単にできます。

4

1.の関数を書き込んだセルの枠の右下あたりにマウスカーソルを動かしてください。

カーソルのアイコンが「+」に変化しますね。この状態でクリックして……

5

クリックしっぱなしで下にぐぐぐっとマウスを動かします。

そして、テキトーな位置でクリックを離すと……

6

この通り!

関数をコピーして、かつセルの参照位置を行に対応して結合してくれています。

3.変換した文字列をコピペしてEclipseに貼りつける(でもその前に……)

それでは、変換した文字列をコピペしてみましょう!

7

セルを選択して、右クリックでコピーします。

意気揚々とEclipseに貼りつけてください。

8

あるぇー? なんかカツオの行が改行されてるし、ダブルクオーテーション増えてるよ?

これは、カツオの備考欄の文章に改行が含まれているためです。

エクセルの改行コードとAndroidの改行コードは違うため、きちんと反映されていないのです。

いったんエクセルの改行コードを置換しないといけません。

エクセルで「ctrl + F」を押すと、検索と置換ウィンドウが表示されます。

9

置換タブを開いて、検索する文字列で「ctrl + J」を押してください。

エクセルの改行コードは「ctrl + J」です。欄に何も表示されませんが、きちんと入っているので安心してください

そして、置換後の文字列には「\n」を入れましょう。

11

これで置換を実行すると、無事に改行が「\n」に置換されました!

この状態でもう一度コピペすると……

12

バッチリです!

4.パターンが複数ある置換は、エクセルの置換や関数ではなく、Eclipseでそのままやっちゃった方が簡単

あと一歩です!

性別の欄をboolean型に変換します。(本来なら性別はint型で格納するのが正しいやり方ですが、今回は色んな型をまとめてエクセルから取り込む方法の解説として書いておりますので、便宜上……)

複数の置換パターンがある場合は、いったんEclipseにコピペしたあとで置換した方が簡単で確実で早いです。

13

このあたりは普段からEclipseを使っている人なら簡単ですよね。

「ctrl + F」で検索・置換ウィンドウが開くので、よしなにしてください。

14

これでエクセルで作られたデータの取り込みが完了しました!

次回の記事では、このデータを扱いやすくクラスとして管理する方法を解説します。

弊社ではインターンを絶賛大募集しています!

 
154529369581
実践力が身に付く、超実践型インターン!! 
健康管理サービス『カラダノート』運営企業! 
★企画営業、★エンジニア、★デザイナー、★サービス運営担当 
株式会社プラスアール|短期バイト求人なら大学生アルバイト.com

 
Android担当エンジニアのインターンとして採用されれば、筆者である私とペアを組んで仕事することになります。 
その際には、就職活動のときや入社してからも即戦力として役立つ超実用的な9つのスキルを教えることを約束します! 
 
 

・JAVAを教えます

Android端末のアプリは、JAVAというプログラム言語で動作しています。 
JAVAはスマートフォンアプリ以外でも広く使われている言語で、アプリ開発を通じてJAVAを使いこなせるようになれば、幅広い業務に対応できます。 
関連記事) 
Activityにまたがってグローバルに変数などのオブジェクトを共有するには 
AndroidでWebViewアプリを作る[初心者向け] 
 
 

・PHPを教えます

・HTMLを教えます

・MYSQLを教えます

・Linuxを教えます

弊社はソーシャルアプリを多数リリース用しており、1つのサービスで1日の最大利用者数が5万に達したこともあります。 
PHP、HTML、MYSQLなどをマスターすれば、WEBサイトが開発できるようになり、アプリ開発だけでなく、WEBエンジニアとしての道も開けてきます。 
関連記事) 
Amimoto AMI 網元『から』別のサーバーにwordpressを移転するとき1 
AndroidアプリでUNIX timeを取得 
 
 

・FLASHを教えます

FLASHはWEBサイトやフィーチャーフォン(ガラケー)のサイトでよく利用されている技術です。 
ターゲットとする分野によっては今でも重要視され、簡単な動画編集などもできる専門性の高い技術です。 
関連記事) 
FlashLite1.1でアドベンチャーゲームをつくる 第1回 『タイプライター風に1文字ずつ文字を表示しよう シーン構成編』 
 
 

・PowerPointを教えます

企画や営業の際に必須になるのがPowerPointです。大学のレポート作りにも即役立つ、便利なツールです。 
PowerPointの使い方やちょっとしたコツを、実際に使われているドキュメントを通して教えます。 
 
 

・Excelを教えます

「正直言うとエクセルの使い方がよく解らない……」という人も多いと思います。 
実務では非常によく使われていますが、基本的な部分から教えていくので安心してください。 
また、関数やマクロといった、一歩進んだ使い方まで指導します。 
関連記事) 
Excelで書かれた「ふりがな付き文字列」をHTMLのタグに対応した文字列に自動で変換する 
 
 

・ギターを教えます!

実務とは全く関係ありませんが、ご希望とあらばギターを教えます! 
……あ、いらない? 
関連記事) 
『Golden Age vol.1』 開催決定!! 
 
 
 
自分の現状のスキルに全く自信がない、という方でも、まずはお気軽にオフィスに遊びに来てください! 温かくお迎えします! 
お待ちしていますm(_ _)m 

AndroidアプリでWebViewを使用しているときに、GooglePlayで配信しているアプリのダウンロードページへのリンクをクリックしても、GooglePlayアプリが起動しないことがあります。

 

(以下の画像は、弊社で配信している『カラダノートforAndroid』で動作させているものです。)

20131120_184633

アプリのダウンロードページへのリンクをクリックすると……

20131120_184750

普通のブラウザでアクセスしようとしてエラーになってしまう。

 

そういう場合は、WebViewをコードで制御して、アクセスするURLによってGooglePlayアプリを起動するなどの処理を実装しましょう。

WebView webView;
webView = (WebView) findViewById(R.id.○○○);

//各種設定
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.setVerticalScrollbarOverlay(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptEnabled(true);

//WebViewに独自のWebViewCliantをセット
webView.setWebViewClient(new MyWebViewClient(MainActivity.this));

このようにWebViewを宣言したのち、セットするWebViewCliantの方で、

public class MyWebViewClient extends WebViewClient {
	Activity mainActivity;

    public MyWebViewClient(Activity mainActivity) {
        super();
        this.mainActivity = mainActivity;
    }

    //ページの読み込み開始
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
    	mainActivity.setProgressBarIndeterminateVisibility(true);
    }

    //ページの読み込み完了
    @Override
    public void onPageFinished(WebView view, String url) {
    	mainActivity.setProgressBarIndeterminateVisibility(false);
    }

    //ページの読み込み失敗
    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        Toast.makeText(view.getContext(), "エラー", Toast.LENGTH_LONG).show();
    }

	// リンクをタップしたときに標準ブラウザを起動させない。
    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
    	// アンドロイドマーケットのときは例外
    	if(url.startsWith("http:") || url.startsWith("https:")) {
    		return false;
    	}
    	Uri uri = Uri.parse(url);
    	Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    	mainActivity.startActivity(intent);
    	return true;
    }
}

こう書くと、
20131120_184447
リンクをクリックすると……
20131120_184505

このようにGooglePlayが起動します!

 

やっぱりAndroidアプリでWebを見ている以上、GooglePlayへのリンクをクリックしたら自動でGooglePlayアプリが立ち上がるようにしたいですよね!

コードがたくさんあって大変でしたね。ここまでお疲れ様でした。今回の記事でプッシュ機能は完成です。

前回の記事のMainActivityのソース内、登録ボタンを押したときの処理に、こんな記述があったと思います。

// レジストレーションIDを取得
mProgress = null;
Handler mHandler = new Handler();

mProgress = new ProgressDialog(context);
mProgress.setMessage(RegisterTask.message);

mProgress.show();
RegisterTask t = new RegisterTask(context, mHandler, mProgress, regid,
                prefs, tv_id);
t.start();

これは通信部分をHandlerで処理しているのですが、その中身がこんな感じです

[RegisterTask.java]

public class RegisterTask extends Thread {
	// レスポンスコード
	int res_code;

	Context context;
	Handler mHandler;
	ProgressDialog mProgress;
	TextView tv_id;

	String regid;
	SharedPreferences prefs;

	// レジストレーションIDをPOSTするURL
	String post_url = "○○○○○○○○○.php";

	public static String message = "少々お待ちください……";
	String TAG = "RegisterTask";

	public RegisterTask(Context context, Handler mHandler,
			ProgressDialog mProgress, String regid, SharedPreferences prefs,
			TextView tv_id) {
		this.res_code = 0;

		this.context = context;
		this.mHandler = mHandler;
		this.mProgress = mProgress;
		this.tv_id = tv_id;

		this.regid = regid;
		this.prefs = prefs;
	}

	// スレッド内処理
	public void run() {
		// 時間がかかる処理
		Log.d(TAG, "postします");

		PostData();

		// スレッドが終了した場合、終了したことをHandlerに知らせる。
		mHandler.post(new Runnable() {
			public void run() {
				// ダイアログを消す
				mProgress.dismiss();
}
		});
	}

	// POST
	private void PostData() {
		// 結果
		String ret = "";

		// インスタンス取得
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);

		try {
			// GCMサーバーへ登録する
			regid = gcm.register(Const.SENDER_ID);

			Log.d(TAG, "regid:" + regid);
		} catch (IOException e) {
			e.printStackTrace();
		}

		// レジストレーションIDを自分のサーバーへ送信する
		URI url = null;
		try {
			url = new URI(post_url);
			Log.d(TAG, "URLはOK:" + post_url);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}

		// POSTするJSONをつくる
		JSONObject kv1 = new JSONObject();
		try {
			kv1.put("regid", regid);
			kv1.put("param1", "param");
			kv1.put("param2", -1);
			kv1.put("param3", false);
		} catch (JSONException e2) {
			e2.printStackTrace();
		}

		String json = kv1.toString();
		Log.d(TAG, "jsonデータ:" + json);

		// POSTリクエストを実行
		DefaultHttpClient httpClient = new DefaultHttpClient();
		try {
			Log.d(TAG, "POST開始");
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new StringEntity(json, "UTF-8"));
			httpPost.setHeader("Content-Type", "application/json");
			httpPost.setHeader("Accept-Encoding", "application/json");
			httpPost.setHeader("Accept-Language", "en-US");

			ret = httpClient.execute(httpPost, new ResponseHandler() {
				@Override
				public String handleResponse(HttpResponse response)
						throws IOException {
					Log.d(TAG, "レスポンスコード:"
							+ response.getStatusLine().getStatusCode());
					res_code = response.getStatusLine().getStatusCode();

					// 正常に受信できた場合は200
					switch (response.getStatusLine().getStatusCode()) {
					case HttpStatus.SC_OK:
						Log.d(TAG, "レスポンス取得に成功");

						// レスポンスデータをエンコード済みの文字列として取得する
						return EntityUtils.toString(response.getEntity(),
								"UTF-8");

					case HttpStatus.SC_NOT_FOUND:
						Log.d(TAG, "データが存在しない");
						return null;

					default:
						Log.d(TAG, "通信エラー");
						return null;
					}
				}
			});
		} catch (IOException e) {
			Log.d(TAG, "通信に失敗:" + e.toString());
		} finally {
			// shutdownすると通信できなくなる
			httpClient.getConnectionManager().shutdown();
		}

		// 受信結果をUIに表示
		Log.d(TAG, "結果:" + ret);

		// 成功したら
		if (res_code == HttpStatus.SC_OK) {
			// レジストレーションIDを端末に保存
			Log.d(TAG, "regid:::" + regid);
			storeRegistrationId(regid);

			//MainActivity画面に反映
			tv_id.setText(regid);
		}
	}

	/*
	 * レジストレーションIDの保存
	 */
	private void storeRegistrationId(String regId) {
		// 今のバージョン
		int currentVersion = 0;
		try {
			PackageInfo packageInfo = context.getPackageManager()
					.getPackageInfo(context.getPackageName(), 0);
			currentVersion = packageInfo.versionCode;
		} catch (NameNotFoundException e) {
		}

		// 保存
		Editor editor = prefs.edit();
		editor.putString(Const.PROPERTY_REG_ID, regId);
		editor.putInt(Const.PROPERTY_APP_VERSION, currentVersion);
		editor.commit();
	}
}

途中、POSTするためのJSONを作っています。
実際に動作させてログを見れば解りますが、ここでは、

{
    "regid"   : 123456,		//int型
    "param1"  : "param",	//String型
    "param2"  : -1,			//int型
    "param3"  : false		//boolean型
}

という形式のJSONを作っています。
このあたりは、どういう形式のJSONを受け取るのか、サーバー側の処理を作成する人と話し合ってください。また、エラーコードやレスポンスについても、サーバーの処理によるので、話し合いが必要です。

さて、これで、レジストレーションIDの登録まで完了しました。
あとはサーバーからのプッシュ通知を受け取るレシーバーを作るだけです。

[GcmBroadcastReceiver.java]

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
	String TAG = "GcmBroadcastReceiver";

	@Override
	public void onReceive(Context context, Intent intent) {
		// 送られてきたデータを受け取る
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
		String messageType = gcm.getMessageType(intent);

		// 送られてきたデータのメッセージ
		Bundle extras = intent.getExtras();
		String mess = extras.toString();

		if (!extras.isEmpty()) {
			// エラー
			if (messageType
					.equals(GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR)) {
				Log.d(TAG, "MESSAGE_TYPE_SEND_ERROR:" + mess);
			}
			// サーバーでメッセージ削除
			else if (messageType
					.equals(GoogleCloudMessaging.MESSAGE_TYPE_DELETED)) {
				Log.d(TAG, "MESSAGE_TYPE_DELETED:" + mess);
			}
			// 正常に受信
			else if (messageType
					.equals(GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE)) {
				Resources res = context.getResources();

				Notification n = new Notification(); // Notificationの生成
				n.icon = R.drawable.ic_launcher; // アイコンの設定

				// 通知されたときに通知バーに表示される文章
				n.tickerText = mess + "(short)"; // メッセージの設定
				n.flags = Notification.FLAG_AUTO_CANCEL; // 通知を選択した時に自動的に通知が消えるための設定

				// 通常の着信音を選択する
				Uri uri = RingtoneManager
						.getDefaultUri(RingtoneManager.TYPE_ALARM); // アラーム音
				n.sound = uri; // サウンド

				Intent i = new Intent(context, MainActivity.class);
				i.putExtra("MESS", mess);

				PendingIntent pi = PendingIntent.getActivity(context, 0, i,
						PendingIntent.FLAG_UPDATE_CURRENT);
				// 上から通知バーを下してきたときに表示される文章をセット
				n.setLatestEventInfo(context, res.getString(R.string.app_name),
						mess + "(long)", pi);

				long[] vibrate_ptn = { 0, 100, 300, 1000 }; // 独自バイブレーションパターン
				n.vibrate = vibrate_ptn; // 独自バイブレーションパターンを設定

				n.defaults |= Notification.DEFAULT_LIGHTS; // デフォルトLED点滅パターンを設定

				// NotificationManagerのインスタンス取得
				NotificationManager nm = (NotificationManager) context
						.getSystemService(Context.NOTIFICATION_SERVICE);
				nm.notify(1, n); // 設定したNotificationを通知する
			}
		}
	}
}

受け取った通知に問題がなければ、Notificationを使って、端末のアラームやバイブレーションを動作させて知らせます。
このあたりはそれぞれお好みの仕様にしてください。

最後に、定数を宣言するクラスを追加すれば完成です。
[Const.java]

public final class Const {
	//プロダクトID
	static final String SENDER_ID = "○○○○○○○○○○○○";

	// SharedPreferences用
	public static final String EXTRA_MESSAGE = "message";
	public static final String PROPERTY_REG_ID = "registration_id";
	public static final String PROPERTY_APP_VERSION = "appVersion";
}

ここまで上手くいっていれば、プッシュ通知を受け取ると、下記の画像のようになっているのではないでしょうか。

20131119_191348

20131119_191408

20131119_191421

以上でプッシュ通知のアプリ側の実装は完了です!

あとは受け取ったメッセージを煮るなり焼くなり好きにしてください!

あ、「削除」ボタンを押したときの処理を書くのを忘れていました……。

基本的にはRegisterTaskと同じように、サーバーに情報を投げて、受け取ったサーバー側はプッシュ通知を配信しないようにするなどのときに使います。RegisterTaskのほぼコピペでOKです。

それでは!