アプリ中断への対処
もし作っているアプリをmobile端末で動かすつもりでいるならアプリの中断に対応させるべきだと思います。中断は例えばAndroidだとHomeボタンを押したり他のアプリを立ち上げる事で生じます。そしてそのまま何事もなく再開できる事もあれば、メモリが足りなくなってOSに破棄される事もあるはずです。この記事では実際にメモ帳を作りながら中断への対応方法を調べていきます。
desktop環境でも中断が起こるようにする
というのも既定では起こらないからです。
from kivy.config import Config
Config.set('kivy', 'pause_on_minimize', 1)
これでdesktop環境でもwindowを最小化する事で中断のtestができるようになりました。
メモ帳アプリのコード
今回はKivyLauncherを使ってAndroid端末で動作確認できるようにしたいので、Python2.7.2+Kivy1.9.2と互換性のあるコードを書いていきます。
from __future__ import print_function
from kivy.config import Config
Config.set('kivy', 'pause_on_minimize', 1)
from kivy.app import App
from kivy.uix.textinput import TextInput
class TestApp(App):
def build(self):
return TextInput()
if __name__ == '__main__':
TestApp().run()
メモ帳と言ってもTextInput
をそのまま使っただけの手抜きですが。
on_pause()
で真を返す
on_pause()
はアプリが中断される時に呼ばれるmethodです。最初に必要なのはこれが真
を返すように実装することです。偽
だとKivyに対して「中断などせずに即座に終了してください」と伝える事になるので。
import sys
def log(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
class TestApp(App):
def on_pause(self):
log('on_pause()')
return True
このon_pause()
ですがKivy1.10.0からは既定で真
を返すようになりましたが、それより前は偽を返すようになっているので、今回のようにKivyLauncher(Kivy1.9.2)に持っていく場合は上書きしないといけません。
on_pause()
の後の展開
on_pause()
が呼ばれた後の展開は2つ確認できており、それは
-
on_resume()
が呼ばれる(アプリが破棄されずに再開できた事を意味する) - 何も呼ばれない(アプリが破棄された事を意味する)
です。破棄される場合はその後なんの機会も与えられないので、何かを保存したいならon_pause()
内でしないといけないという事になります。
on_pause()
で保存する
from os.path import join as ospath_join
import io
class TestApp(App):
def on_pause(self):
log('on_pause()')
self.save_session()
return True
def on_resume(self):
log('on_resume()')
@property
def savefilepath(self):
return ospath_join(self.user_data_dir, 'savedata.txt')
def save_session(self):
with io.open(self.savefilepath, 'wt', encoding='utf-8') as writer:
writer.write(self.root.text)
中で使っているuser_data_dir
ですが、これはApp
のpropertyで、データの保存先として適したdirectoryへのpathが得られます。
アプリ開始時に復元する
そしてアプリ開始時には保存データがあるか確かめ、あれば復元します。
from os.path import join as ospath_join, isfile as ospath_isfile
import io
class TestApp(App):
def on_start(self):
log('on_start()')
self.restore_session()
def restore_session(self):
path = self.savefilepath
if not ospath_isfile(path):
return
with io.open(path, 'rt', encoding='utf-8') as reader:
self.root.text = reader.read()
正常終了時にも保存する
その方が便利でしょう。
class TestApp(App):
def on_stop(self):
log('on_stop()')
self.save_session()
完成
from __future__ import print_function
from kivy.config import Config
Config.set('kivy', 'pause_on_minimize', 1)
from kivy.app import App
from kivy.uix.textinput import TextInput
from os.path import join as ospath_join, isfile as ospath_isfile
import io
import sys
def log(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
class TestApp(App):
def build(self):
return TextInput()
def on_pause(self):
log('on_pause()')
self.save_session()
return True
def on_resume(self):
log('on_resume()')
def on_start(self):
log('on_start()')
self.restore_session()
def on_stop(self):
log('on_stop()')
self.save_session()
@property
def savefilepath(self):
return ospath_join(self.user_data_dir, 'savedata.txt')
def save_session(self):
with io.open(self.savefilepath, 'wt', encoding='utf-8') as writer:
writer.write(self.root.text)
def restore_session(self):
path = self.savefilepath
if not ospath_isfile(path):
return
with io.open(path, 'rt', encoding='utf-8') as reader:
self.root.text = reader.read()
if __name__ == '__main__':
TestApp().run()
ソースコードはandroid.txtも含めてgistに上げてあります。