Android, 時々Web

Androidアプリを作ったり、Webサービスを作ったりする中で困ったことや詰まったことを解決したときの備忘録です。備忘録なので、正しい答えが書いてあるとは限りません。

Android Studioでパッケージ名を(Company Domainも含めて)変更する

Android Studioでパッケージ名を変更しようと思ったが、たしか結構面倒だった気がしたので、ggっていくつか参考サイトを読んでみた。

 

すると、

【AndroidStudio:もっとお手軽☆パッケージ名変更】build.gradleから簡単に! - Qiita

Androidアプリのパッケージ名を最速で変更 -でじうぃき

https://www.makistone.com/2015/01/28/post-70/

このようにたくさんヒットして、書いてあるからにはそれでうまくいくこともあると思うのだが、app>Java>[パッケージ名]で右クリックして、Refactor->Renameとしても最後の部分(アプリケーション名?)のみしか変更できないようだ。

また、先ほど挙げた参考サイトにもあるように、build.gradle(module)のapplicationIdや、Manifest.xmlのmanifest要素のpackage属性などを変更して、Sync Project with Gradle Fileしてもパッケージ名は自動では変更されなかった。

 

ということで、そのようにあまり自動的にリファクタリングしてくれない場合に、このようにすればとりあえず動いたということをメモ。

 

  1. moduleのbuild.gradleのapplicationIdを変更する。
  2. Manifest.xmlのmanifest要素のpackage属性を変更する
  3. app>javaのパッケージ名を右クリックして、Show in Explorerでエクスプローラでフォルダの位置を開く。
  4. comやexampleなどの(このフォルダ名は変更前のパッケージ名に従っている)フォルダ構成を、変更したいパッケージ名のフォルダ構成になるように削除したり作成したり名前を変更したりする。
  5. app->java->[パッケージ名]の下のjavaファイルにエラーが出るので、それを1つずつ開いて最上部のpackageを変更後のパッケージ名になるように変更する。(赤い波線になっている部分をクリックして、Alt+Enterして自動補完を使っても良い)
  6. おそらくimportしてる部分もエラーが発生していると思うので、そこも直す。
  7. Sync Project with Gradle Fileする。
  8. ビルドが通る!

 

これで何とか動いた。

とはいいつつこんな力技でいいのかは不安が残る。動いたからよし。

画面回転によるActivityの再起動に対応する

※この記事はあまりよく理解していない人が書いているので、あまり参考にしないでください。

 

さて前置きしたところで、

今までActivityの再起動、再作成が面倒だったので、画面を回転できないように固定するという解決策を取っていたが、そうは言ってられなくなったので対応したのでメモ。

Activityが再作成されて何が問題かというと、自分が分かる範囲では、

1.インスタンス変数などが初期化される。

2.onCreateが再び呼ばれる。

ということです。つまり、もう一度最初から処理が走ってしまうし、その時の変数は完全に失われているということ。

これに対応するために、onSaveInstanceStateとかonRestoreInstanceStateなどを使うらしい。

(ところでonCreate時に渡される引数、savedInstanceStateとはいつ使うのだろうか?)

 

簡単に例を挙げると、こんな感じ。

@Override
public void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
state.putString("FILE_PATH", mSavedImageFilePath);
}

@Override
public void onRestoreInstanceState(Bundle state){
super.onRestoreInstanceState(state);
mSavedImageFilePath = state.getString("FILE_PATH");
}

こうやってインスタンス変数をBundleにputして、そしてリストアされるときにインスタンス変数にBundleからgetしたものを代入する。

そうすることで画面回転前と後でインスタンス変数が共有される。

 

あと、onCreateにもう一度走ってしまうと不都合があるコードが含まれているのなら、

if( savedInstanceState == null){
// ここに再作成時には実行したくない処理
}

という風にしておくと2回目以降の再作成では実行されない。

暗黙的Intentで画像を渡す(表示、共有、編集)

Androidで他のアプリに何か処理を投げたいときには、Intentというものを使う。

明示的Intentと暗黙的Intentというものがあって、明示的Intentは呼び出したいActivityのClassを直接指定する。

暗黙的Intentは呼び出したいActivity(というかアプリ)の種類や、どういうことをしてほしいかといったことを設定して投げると「俺それ出来るよ!」ってアプリが担当してくれる。

 

ということは良く知られてることで、頻繁に使うことなんだけど、自分で作ったり保存した画像を他のアプリに渡したいときに、Intentに画像を指定する方法でハマった。

いろんな方法がインターネットに乗ってたけど、Intentを受け取ってはくれるものの画像が読み込めないで不正終了してしまうなんてことがよく合った。

デフォルトのギャラリーやGoogle謹製のフォトなんかもエラー落ちしてしまうということは、こっちのIntentの投げ方が悪いということだ。

 

結論からいって、こうすれば動いた。

画像はローカルにファイルとして保存されている必要があるらしい(そう思えない挙動をするアプリがあるから、必ずしもそうだとは限らないけど、それ以外に方法が見つからなかった)。 

    File file = new File("保存されている画像へのパス");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "image/png");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
startActivity(intent);

Intent.setActionで、アクションを指定する。

Intent.ACTION_VIEWを指定すると表示、
Intent.ACTION_SHAREを指定すると共有、
Intent.ACTION_EDITを指定すると編集を行うアプリを呼び出せる。

 

画像をDataとExtraの両方で指定するのがミソ。

受取先のアプリがどっちを必要としているかわからないので、両方指定することにした。

(というのも、VIEWとEDITはDataを指定するだけでうまく行ったのだが、SHAREはExtraにしないとうまくいかないことが多かった。)