著者アーカイブ asaba

asaba 著者:asaba

【java】StringBuilderでデータをまとめてpostで送る

StringBuilderを使ってhttpURLConnectionで好きなだけデータを

postする汎用メソッドを作りました。

 

使い方はシンプルで、ただ拡張for文を使って回すだけなので

特別な制約は無いです。

 

</pre>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

StringBuilder contentsBuilder = new StringBuilder();
Map<String, String> map = new HashMap<>();
String str = "hello!!";
double lat = 34.222222;
double longi = 137.111111;
String line = ",";
String strlati = String.valueOf(lat);
String strlong = String.valueOf(longi);
map.put("string", str);
map.put("latitude", strlati);
map.put("longitude", strlong);
for (String val : map.values()) {
if (contentsBuilder.length() > 0) {
contentsBuilder.append(line);
}
contentsBuilder.append(val);
}
}
<pre>

変数latとlongiはdoubleですが、途中でString.valueOf()で変換することで

送ることができるようになります。

 

もしサーバー側で変換したい場合は、\nとか、ごとに切り分けた後に

各値に合った型に戻してあげればいけそうですね。

 

本当はもっと簡単に書きたかったですがこの辺で妥協します。

asaba 著者:asaba

【java】ライブラリを使わずに文字列を反転させる

入力した文字列を反転させるミニアプリを作りました。

ライブラリを使えばこんな手間なんてかからないのですが、

なんとなく生のjavaを触って反転させたいと思ったのがきっかけです。

 


public class MainActivity extends AppCompatActivity {
EditText ed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.altBtn);
ed = findViewById(R.id.mountingText);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String beforeAlterText;
beforeAlterText = ed.getText().toString();
char[] chars = beforeAlterText.toCharArray();
int i = beforeAlterText.length();
if(i % 2 == 0) {
int dev = i / 2;
for(int j = 0; j < dev; j++){
char temp = chars[j];
chars[j] = chars[i – j – 1];
chars[i – j – 1] = temp;
}
System.out.println(chars);

}else if(i % 2 == 1){
int notdev = i / 2 + 1;
for(int j = 0; j < notdev; j++){
char temp = chars[j];
chars[j] = chars[i – j – 1];
chars[i – j – 1] = temp;
}
System.out.println(chars);
}
}
});
}
}


 

最初の分岐で奇数か偶数か判別した後に入力した文字を2で割って中間地点を決めます。

この中間地点まで文字を反転させるといった感じになっています。

 

バブルソートは値の大小を判断しますがここではただの文字列

なのでそのまま文字を置き換えています。

 

文字は出てこないですがSystem.outで反転後の文字列が

確認することができます。

以上ですが見ての通り中身が何もないです。

ttsとか使って応用できればもっと面白そうなアプリが作れるかもしれません。

とりあえずソートの練習をしたいとか見てみたいとか思ったら試してみてください。

 

P.S.余談ですが、自分はこのコードの中で文字列を

退避するところをゴミ箱って呼んでます。

 

asaba 著者:asaba

【androidjava】大量のファイルをローカルリポジトリからgithubに追加する方法

create-react-appは、facebookが開発したreact開発者向けのスターター

ツールです。babelやwebpackといった面倒なところの作業をせずに

いきなり開発できるので、reactの敷居が低くなり開発ユーザーが

どっと増えたことで脚光を浴びました。

 

今回はそのcreate-react-appをgithubに入れようと早速ダッシュボードで

create-react-appの全ファイルをドラッグしてアップロードしようと

したのですが、ファイルが多すぎて

Yowza, that’s a lot of files. Try again with fewer than 100 files. create react app

の警告を受けたのでgithubから直接アップロードするのは断念。

 

とりあえず無理やりローカルから入れてソースツリー側から

プッシュをすることにしました。

 

手順はこんな感じ↓

 

①まずgithubで適当にリポジトリを作る

②できたリポジトリのアドレスをコピー

③ソースツリーで先ほどコピーしたアドレスをクローンして

ローカルリポジトリを作成する

④create-react-app内のファイルを全てコピー

⑤クローンで生成されたファイルの中身をgit以外全て消去

⑥ファイルを全てぶちこむ(なにもない場合はそのまま入れる)

 

以上で作業は完了です。^^

 

このコピーが結構時間がかかるの

ですが、無事に終了すればソースツリーの未コミットの欄に

さきほど入れたcreate-react-appの中身が確認できます。

後はnpm startでapp.jsが正常に動作すれば移行の成功です。

 

ローカルリポジトリの中でcreate-react-appをしても二重フォルダに

なってややこしいので、こちらが一番わかりやすいと思い実践しました。

asaba 著者:asaba

【androidjava】Bitmap初期化失敗した時に確認すること

googlemapを使う時にマーカーをカスタマイズしたい時に

bitmapを使うのですが、googlemapと併用する際は

始動時のonMapReadyの中で処理をする必要があります。

 

これは、Google Map の用意が出来た時に初めて初期化できる状態に

なるからです。

 

なのでonCreate内でbitmapを初期化

しようとするとエラー「IBitmapDescriptorFactory is not initialized」

で初期化が失敗してしまいます。

 

</pre>
@Override
public void onMapReady(GoogleMap googleMap) {

//この中でforを使いたい場合

BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(myImageList[i]);

ClusterModel offsetItem = new ClusterModel(title[i],url[i], icon);

}
<pre>

 

なんでもフィールドやonCreate内で初期化するのも

よくないということですね。

asaba 著者:asaba

【android・googlemap】DefaultClusterRendererをオーバーライドしたカスタマイズ法

DefaultClusterRendererを継承したクラスを作ってオーバーライドして

値を変えることで自分好みのマップを作ることができます。

例えば、addmarkerを使わずにsetInfoWindowAdapterと併用して

マーカーをカスタマイズしたい時は、DefaultClusterRendererを継承した

クラスの中にonBeforeClusterItemRenderedをオーバーライドした

メソッドを書くことでマーカーのアイコンを変更することができます。

 

マーカーを変更したい時はこちらも

お忘れなく。↓

</pre>
public class ClusterModel implements ClusterItem {
private LatLng mPosition;
private String mTitle;
private String mSnippet;
private BitmapDescriptor mIcon;

//一番最後にBitmapDescriptorを追加

public ClusterModel(double lat, double lng, String title, String snippet,BitmapDescriptor icon) {
mPosition = new LatLng(lat, lng);
mTitle = title;
mSnippet = snippet;
mIcon = icon;
}

@Override
public LatLng getPosition() {
return mPosition;
}

@Override
public String getTitle() {
return mTitle;
}

@Override
public String getSnippet() {
return mSnippet;
}
public BitmapDescriptor getIcon() {
return mIcon;
}
}
<pre>

 

こちらはメインアクティビティ↓

 

</pre>
@Override
public void onMapReady(GoogleMap googleMap) {
mMap= googleMap;
//クラスターインスタンス化
mClusterManager = new ClusterManager<ClusterModel>(this, mMap);
mClusterManager.setRenderer(new MarkerRenderer(this, mMap, mClusterManager));
mClusterManager.setOnClusterClickListener(this);
mMap.setOnCameraIdleListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
for(int i =0; i < points.size(); i++) {
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(myImageList[i]);
ClusterModel offsetItem = new ClusterModel(pointX[i], pointY[i],title[i],url[i], icon);
mClusterManager.addItem(offsetItem);
}
}
<pre>

 

アクティビティ内に以下のクラスを追加↓

 

</pre>
private class MarkerRenderer extends DefaultClusterRenderer<ClusterModel>{
public MarkerRenderer(Context context, GoogleMap map, ClusterManager<ClusterModel> clusterManager) {
super(context, map, clusterManager);
}
@Override
protected int getColor(int clusterSize) {
return Color.rgb(0, 255, 255);
}
@Override
public void onBeforeClusterItemRendered(ClusterModel markerItem, MarkerOptions markerOptions) {
if (markerItem.getIcon() != null) {
markerOptions.icon(markerItem.getIcon());
}
markerOptions.visible(true);
}
}
<pre>

 

onBeforeClusterItemRenderedは、アイコンが出る前にrenderする(アイコンの更新

や動きを決める)役割を持ったメソッドです。

つまり、アイコンの見た目を変えたい場合はこちらをオーバーライドして

設置しておけば画像を受け取って変更してくれるという訳です。

 

addmarkerは同期してマーカーがrenderされるので遅い&容量食らうのでメモリ不足

になりがちですが、ClusterManagerと組み合わせて非同期で

renderすることで、マーカー・クラスターが増えても高速でrender

をしてくれるので多少複雑に作ってもこっちを作った方が

よさそうです。

asaba 著者:asaba

【androidjava】Linkifyで簡単にテキストリンクを作る

androidでテキストとリンクの混合テキストを作る方法の一つに

Linkifyライブラリを使う方法があります。

 

こちらがサンプル

 

</pre>
<pre>TextView text = findById(this, R.id.sample);
text.setText(R.string.sampleText);
Linkify.addLinks(text, Linkify.ALL);

第一引数にリンクを付けたいテキスト、第二引数に

リンクとして出したい形式を渡します。

 

第二引数の形式に合ったテキストを第一引数の中から

あぶりだして該当したテキストをリンクに変換する

と覚えましょう。簡素ですが覚えましょう。

 

ここではhttps://の形式でリンクを作りたいのでallとしています。

他にも電話番号をあぶりだすPHONE_NUMBERSや住所をリンク

にできるmapaddress(こちらはすでに非推奨)がありますが、

allは全て対象に含んでくれるのでリンクを作りたいと

思ったら迷わずこれでいいと思います。

 

asaba 著者:asaba

【androidjava】ClusterManagerでクラスターを作る

Android Utility Libraryの一つであるClusterManagerを使ってみました。

 

これを使って位置登録で地図にあふれ出たマーカーを

ズームアウトすると、周辺のマーカーを吸収してひとまとめに

して表示してくれます。

 

撮った写真を地図に逐次追加したいアプリに向いていますね。

 

追加方法は、まずClusterModelを作ります。

 

</pre>
public class ClusterModel implements ClusterItem {
private LatLng mPosition;
private String mTitle;
private String mSnippet;

public ClusterModel(double lat, double lng, String title, String snippet) {
mPosition = new LatLng(lat, lng);
mTitle = title;
mSnippet = snippet;
}

@Override
public LatLng getPosition() {
return mPosition;
}

@Override
public String getTitle() {
return mTitle;
}

@Override
public String getSnippet() {
return mSnippet;
}
}
<pre>

 

続いて表示したいアクティビティに次のように書きます。

 

</pre>
private ClusterManager<ClusterModel> mClusterManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report);
}

@Override
public void onMapReady(GoogleMap googleMap) {

mClusterManager = new ClusterManager<ClusterModel>(this, mMap);
mMap.setOnCameraIdleListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);

for(int i =0; i < points.size(); i++) {
ClusterModel offsetItem = new ClusterModel(pointX[i], pointY[i],title[i],url[i]);
mClusterManager.addItem(offsetItem);
}
}

mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
return null;
}
@Override
public View getInfoContents(Marker marker) {
View view = getLayoutInflater().inflate(R.layout.info_window, null);
TextView title = (TextView)view.findViewById(R.id.info_title);
title.setText(marker.getTitle());
ImageView imageView = (ImageView) view.findViewById(R.id.info_image);
Picasso.with(ReportActivity.this)
.load(marker.getSnippet())
.placeholder(R.drawable.sample)
.resize(200,200)
.into(imageView,new MarkerCallback(marker,marker.getSnippet(),imageView));

return view;
}
<pre>

 

ClusterModelインスタンスで定義した緯度経度・タイトル・urlを

順に出していきたいためforで回しています。

 

画像を出したい時はまたpicassoで読み込んでいきます。

 

複雑になってしまいましたがこれで晴れてクラスターを使えるように

なりました。

 

asaba 著者:asaba

【androidjava】FusedLocationProviderについて

撮影した写真の位置情報が付いてこなかった時に現在位置を取ってきて

それを代わりに使う機能を作りました。

 

FusedLocationProviderがでるまでは、gps、wifi、電話といった受信機器

から開発者で切り分けていましたが

これを実装すると、どの機器からも処理を分岐させる

必要がなくなり楽に受信処理を書くことができます。

 

locationmanagerよりもかなり短くお手軽に書けました。

 

まず最初にパーミッションを付けましょう。他の

uses-permissionがついているところに適当にぶちこみます。

 

&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
・・・
・・・
・・・
</manifest>

リクエストを受け取る為にインスタンスを作ります。

 

 


private FusedLocationProviderClient fusedLocationClient;

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//コンストラクタはthisでok
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
getLastLocation();
}

//現在地を緯度経度の形で受け取る

private void getLastLocation() {
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(
                        this,
                        new OnSuccessListener<Location>() {
                            @Override
                            public void onSuccess(Location location) {
                                System.out.println("asaba");
                                latitude = location.getLatitude();
                                longitute = location.getLongitude();
                                latLng = new LatLng(latitude, longitute);
                                MapFragment mapFragment = (MapFragment) getFragmentManager()
                                        .findFragmentById(R.id.mapFragment);
                                mapFragment.getMapAsync(MainActivity.this);
                            }
                        });
    }

getLastLocation()で通信に成功した場合にlatitudeとlongituteを

取ってきます。

注意するべきは、MapFragmentの定義位置です。

onCreate内でこれを呼ぶと、mapFragmentがgetLastLocation()より

早く呼ばれてしまい、latLngがnullとなりアプリがクラッシュして

しまう点です。

必ず同じスコープ内で処理をしておきましょう。

latitudeとlongituteをSystem.out.println();で表示して

現在地が読み取れれば成功です。

 

リファレンスはこちら→https://developer.android.com/training/location/retrieve-current.html

asaba 著者:asaba

【androidjava】複数のspinnerでの値の切り分け方

複数のspinnerを設置した時に

spinner別に値を持ってくるにはどうするのかというと

 

onItemSelectedの第一引数である

AdapterView<?> parentの値をswitchの引数に当てはめて

実際に動かしているspinnerの名前を取得した後に

getSelectedItem().toString()をすることでspinnerの項目名を

取ってくることができます。

 

</pre>
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
switch(parent.getId()){
case R.id.lacal_spinner :
String l = upperspinner.getSelectedItem().toString();
System.out.println(l);
break;
case R.id.language_spinner :
String la = underspinner.getSelectedItem().toString();
System.out.println(la);
break;
}
}
<pre>

今回はちゃんとリファレンスを読んだ後コードを書いたので

平穏でした。

(間違えてviewから何か取ろうとしてたなんて言えない。)

 

 

asaba 著者:asaba

【android・picasso】picassoのコールバック処理について

前回これすごくいいと騒いでいたpicassoの件です。

 

設定したマーカーをタップしてpicassoで読み込んだ画像を

表示するまでが期待値だったのですが、

一エリアのマーカーの一回目のタップに必ず

プレースホルダーが表示される現象がおきました。

 

こちらの原因は、picasso自体参照が弱いため。intoに入れる素材が

imageViewだけだとpicassoが画像を取れなくても

読み込んだ行為=画像を読み込んだと誤認識

してしまうため、デフォルトのプレースホルダーの

画像を表示してしまうみたいです。

正しく使うためには、picassoのコールバックを使う必要があります。

前回書いたコードにinto(ImageView, Callback)を追加します。

 

</pre>
//吹き出しカスタマイズ
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
return null;
}
@Override
public View getInfoContents(Marker marker) {
// 今回はこちらに処理を記述
View view = getLayoutInflater().inflate(R.layout.info_window, null);
// タイトル設定
TextView title = (TextView)view.findViewById(R.id.info_title);
title.setText(marker.getTitle());
ImageView imageView = (ImageView) view.findViewById(R.id.info_image);
Picasso.with(ReportActivity.this)
.load(marker.getSnippet())
.placeholder(R.drawable.sandclock)
.resize(200,200)
.into(imageView,new MarkerCallback(marker,marker.getSnippet(),imageView));

return view;
}
});
<pre>

 

ここまでは前回と一緒です。続いてコールバックの実装。

 

</pre>
public class MarkerCallback implements Callback {
Marker marker = null;
String URL;
ImageView userPhoto;

MarkerCallback(Marker marker, String URL, ImageView userPhoto) {
this.marker = marker;
this.URL = URL;
this.userPhoto = userPhoto;
}

@Override
public void onError() {
//Log.e(getClass().getSimpleName(), "Error loading thumbnail!");
}

@Override
public void onSuccess() {
if (marker != null && marker.isInfoWindowShown()) {
marker.hideInfoWindow();

Picasso.with(ReportActivity.this)
.load(URL)
.into(userPhoto);

marker.showInfoWindow();
}
}
}
<pre>

picassoが読み込みに成功したら必ずコールバックで値の更新を

行います。

ここではmarker、URL、userPhoto再度onSuccessで

picassoに渡して更新しています。

 

これでプレースホルダーが呼ばれることなく読み込んだ画像を

ちゃんと表示してくれるようになりました。

 

調べてみるとstackoverflowにも似たような記事がありました。

https://stackoverflow.com/questions/32725753/picasso-image-loading-issue-in-googlemap-infowindowadapter/40045697#40045697

 

qiitaにも

https://qiita.com/Nkzn/items/a285196a88a21b80b9bf

 

リファレンスを飛ばしてしまいがちだったのでそのしっぺ返しが

きてしまった感じですね。