Androidで通知欄をクリックした後、アプリを起動してからターゲットActivityを開く
11101 ワード
状況の概要
Androidアプリを開発する過程で、appでは独立したプロセスで動作し、サーバーと長い接続を保ち、サーバーから送られてきたメッセージを通知欄に表示し、クリック動作を設定し、クリックしてappに対応するActivityにジャンプするサービスを起動する必要がある.現在発生している問題は、サービスが独立したプロセスで実行され、メッセージが受信され、通知がポップアップされた後、app自体のプロセスには2つの状況があります.
appはを実行しています
appはを終了しました
1つ目の場合、処理は非常に簡単で、パラメータをIntentに直接入力し、対応するActivityを開くことができます.
しかし、第2のケースは、appが終了したため複雑であり、開くActivityのいくつかの操作はappの初期化に依存する必要があり、これらの初期化操作はappの起動中に行われる.例えば、あるショッピングアプリはある新商品のメッセージをプッシュし、ユーザーは通知をクリックして商品の詳細のActivityに入り、そのActivityには注文Buttonがあり、そのButtonをクリックするとローカルからユーザーのIdなどの情報を取得してサーバーにメッセージを送り、あるユーザーがその商品を注文したことをサーバーに伝える.これらのユーザ情報はapp起動時にサーバと一連のインタラクションを行った後に取得される.アプリ終了後に詳細Activityに直接アクセスして購入をクリックすると、ユーザー情報が取得できずエラーが発生します.
したがって、現在解決すべき問題は、Notificationでクリック動作を設定し、app自体が実行されている場合は、ターゲットActivityに直接ジャンプします.appが終了した場合は、appを起動して初期化を完了し、ターゲットActivityにジャンプします.
方案と構想
現在3つのActivityがあると仮定します.
SplashActivityは、appの大図を表示しながらユーザー登録などの操作を行い、サーバがデータを返してMainActivityにジャンプします.
MainActivityアプリのメインActivity.
DetailActivity MainActivityでButtonが入ったActivityをクリックして、ある商品の詳細を表示します.
また、ポップアップ通知のサービスは別のプロセスにあります.
私たちが達成しなければならない目的は:
通知欄の通知をクリックし、appが実行中である場合、直接DetailActivityにジャンプして具体的な内容を表示し、DetailActivityでBackキーを押してMainActivity に戻る
通知欄をクリックして、appが終了した場合、SplashActivityから入り、app起動画面を表示し、初期化操作が完了したらMainActivityに入り、DetailActivityにジャンプして具体的な内容を表示し、DetailActivityでBackキーを押してMainActivityに戻るように通知します.
初歩的な考え方は,まずappプロセスが存在するか否かを判断し,存在する場合はstartActivitiesを用いてMainActivityとDetailActivityを起動することである.なぜ直接DetailActivityだけを起動せずにMainActivityを起動するのですか?プロセス内のすべてのActivityが終了している場合がありますが、プロセスがシステムによって回収されていない場合は、プロセスに戻りtrueがあるかどうかを判断し、DetailActivityのみを起動すると、Backキーを押すとタスクスタックはそのままデスクトップに戻ります.私たちが望む効果は、Backキーを押して前のレベルのActivity、つまりMainActivityに戻ることです.
アプリプロセスが終了して存在しなくなった場合は、SplashActivityに転送された後、SplashActivityからMainActivityに転送され、MainActivityに判断が加えられ、このパラメータがあれば通知欄から起動したことを示し、DetailActivityにジャンプする操作を行うIntentでアプリケーションを起動します.そうでない場合は、通常の起動です.
コード実装
大まかな実現構想ができたら、demoを実際に操作してみましょう.まず、私たちのdemoには簡単なコンポーネントがあります.
PushServiceは、新しいプロセスで起動されたサービスで、サーバの傍受を担当し、サーバの情報を受信した後にメッセージをブロードキャストします.このdemoでは、簡略化のため、メッセージを簡単にブロードキャストします.
ShowNotificationReceiver、新しいプロセスに登録されているBroadcastReceiverは、PushServiceからのメッセージを受信すると、通知バーにという通知がポップアップされます.
NotificationReceiver、新しいプロセスに登録されたBroadcastReceiverは、通知バーをクリックして通知する動作を設定し、appのActivity を開く
SplashActivity,app起動ページは、まず起動画像、3 s後にMainActivity に入ります.
MainActivity,appのメインActivity DetailActivity,appに詳細を表示するActivity PushService.java
まずPushServiceです.新しいプロセスで起動するにはAndroidManifestです.xmlに以下のサービス登録コードを追加
PushServiceの作業は簡単で、起動後にブロードキャストを送信して通知欄に通知を表示し、バックグラウンドに常駐します.
ShowNotificationReceiver.java
このブロードキャストクラスは、通知バーで通知をポップアップするために使用されます.
NotificationReceiver.java
通知欄をクリックすると、アナウンスが送信され、NotificationReceiverがそのアナウンスを受信すると、appプロセスが存続しているか否かが判断され、appプロセスの状態によって異なるapp起動方式が定義されます
SplashActivity.java
SplashActivity.JAvaはまずappが起動した画像で、3 s後にMainActivityに入り、SplashActivityを起動したIntentにパラメータがついている場合はパラメータを取り出し、MainActivityを起動したIntentに入れる
MainActivity.java
MainActivityでは、パラメータ入力がある場合は初期化終了後、パラメータに従ってDetailActivityを起動し、パラメータ入力がない場合は自分のタスクを終了します
DetailActivity.java
入力パラメータを表示すると簡単です.-D
効果の表示
http://v.youku.com/v_show/id_XMTMwMjgyNTUwMA==.html?from=y1.7-1.2
demoダウンロード
https://github.com/slimhippo/androidcode
Androidアプリを開発する過程で、appでは独立したプロセスで動作し、サーバーと長い接続を保ち、サーバーから送られてきたメッセージを通知欄に表示し、クリック動作を設定し、クリックしてappに対応するActivityにジャンプするサービスを起動する必要がある.現在発生している問題は、サービスが独立したプロセスで実行され、メッセージが受信され、通知がポップアップされた後、app自体のプロセスには2つの状況があります.
appはを実行しています
appはを終了しました
1つ目の場合、処理は非常に簡単で、パラメータをIntentに直接入力し、対応するActivityを開くことができます.
しかし、第2のケースは、appが終了したため複雑であり、開くActivityのいくつかの操作はappの初期化に依存する必要があり、これらの初期化操作はappの起動中に行われる.例えば、あるショッピングアプリはある新商品のメッセージをプッシュし、ユーザーは通知をクリックして商品の詳細のActivityに入り、そのActivityには注文Buttonがあり、そのButtonをクリックするとローカルからユーザーのIdなどの情報を取得してサーバーにメッセージを送り、あるユーザーがその商品を注文したことをサーバーに伝える.これらのユーザ情報はapp起動時にサーバと一連のインタラクションを行った後に取得される.アプリ終了後に詳細Activityに直接アクセスして購入をクリックすると、ユーザー情報が取得できずエラーが発生します.
したがって、現在解決すべき問題は、Notificationでクリック動作を設定し、app自体が実行されている場合は、ターゲットActivityに直接ジャンプします.appが終了した場合は、appを起動して初期化を完了し、ターゲットActivityにジャンプします.
方案と構想
現在3つのActivityがあると仮定します.
SplashActivityは、appの大図を表示しながらユーザー登録などの操作を行い、サーバがデータを返してMainActivityにジャンプします.
MainActivityアプリのメインActivity.
DetailActivity MainActivityでButtonが入ったActivityをクリックして、ある商品の詳細を表示します.
また、ポップアップ通知のサービスは別のプロセスにあります.
私たちが達成しなければならない目的は:
通知欄の通知をクリックし、appが実行中である場合、直接DetailActivityにジャンプして具体的な内容を表示し、DetailActivityでBackキーを押してMainActivity に戻る
通知欄をクリックして、appが終了した場合、SplashActivityから入り、app起動画面を表示し、初期化操作が完了したらMainActivityに入り、DetailActivityにジャンプして具体的な内容を表示し、DetailActivityでBackキーを押してMainActivityに戻るように通知します.
初歩的な考え方は,まずappプロセスが存在するか否かを判断し,存在する場合はstartActivitiesを用いてMainActivityとDetailActivityを起動することである.なぜ直接DetailActivityだけを起動せずにMainActivityを起動するのですか?プロセス内のすべてのActivityが終了している場合がありますが、プロセスがシステムによって回収されていない場合は、プロセスに戻りtrueがあるかどうかを判断し、DetailActivityのみを起動すると、Backキーを押すとタスクスタックはそのままデスクトップに戻ります.私たちが望む効果は、Backキーを押して前のレベルのActivity、つまりMainActivityに戻ることです.
アプリプロセスが終了して存在しなくなった場合は、SplashActivityに転送された後、SplashActivityからMainActivityに転送され、MainActivityに判断が加えられ、このパラメータがあれば通知欄から起動したことを示し、DetailActivityにジャンプする操作を行うIntentでアプリケーションを起動します.そうでない場合は、通常の起動です.
コード実装
大まかな実現構想ができたら、demoを実際に操作してみましょう.まず、私たちのdemoには簡単なコンポーネントがあります.
PushServiceは、新しいプロセスで起動されたサービスで、サーバの傍受を担当し、サーバの情報を受信した後にメッセージをブロードキャストします.このdemoでは、簡略化のため、メッセージを簡単にブロードキャストします.
ShowNotificationReceiver、新しいプロセスに登録されているBroadcastReceiverは、PushServiceからのメッセージを受信すると、通知バーにという通知がポップアップされます.
NotificationReceiver、新しいプロセスに登録されたBroadcastReceiverは、通知バーをクリックして通知する動作を設定し、appのActivity を開く
SplashActivity,app起動ページは、まず起動画像、3 s後にMainActivity に入ります.
MainActivity,appのメインActivity DetailActivity,appに詳細を表示するActivity PushService.java
まずPushServiceです.新しいプロセスで起動するにはAndroidManifestです.xmlに以下のサービス登録コードを追加
<service android:name=".PushService"
android:process=":push"/>
PushServiceの作業は簡単で、起動後にブロードキャストを送信して通知欄に通知を表示し、バックグラウンドに常駐します.
public class PushService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i("PushService", "PushService onCreate");
// AlarmManager
AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, ShowNotificationReceiver.class);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.set(AlarmManager.ELAPSED_REALTIME, SystemClock.currentThreadTimeMillis(), pendingIntent);
}
}
ShowNotificationReceiver.java
このブロードキャストクラスは、通知バーで通知をポップアップするために使用されます.
public class ShowNotificationReceiver extends BroadcastReceiver{
private static final String TAG = "RepeatReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "ShowNotificationReceiver onReceive");
//
Intent broadcastIntent = new Intent(context, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.
getBroadcast(context, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentTitle(" ")
.setTicker(" ticker")
.setContentIntent(pendingIntent)
.setSmallIcon(android.R.drawable.ic_lock_idle_charging);
Log.i("repeat", "showNotification");
NotificationManager manager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(2, builder.build());
}
}
NotificationReceiver.java
通知欄をクリックすると、アナウンスが送信され、NotificationReceiverがそのアナウンスを受信すると、appプロセスが存続しているか否かが判断され、appプロセスの状態によって異なるapp起動方式が定義されます
public class NotificationReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// app
if(SystemUtils.isAppAlive(context, "com.liangzili.notificationlaunch")){
// , DetailActivity, , app
// Task , Back , ,
//DetailActivity, Back MainActivity 。
//DetailActivity , MainActivity。
Log.i("NotificationReceiver", "the app process is alive");
Intent mainIntent = new Intent(context, MainActivity.class);
// MainAtivity launchMode SingleTask, flag Intent.FLAG_CLEAR_TOP,
// Task MainActivity , , Activity ,
// Task MainActivity ,
mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent detailIntent = new Intent(context, DetailActivity.class);
detailIntent.putExtra("name", " ");
detailIntent.putExtra("price", "58 ");
detailIntent.putExtra("detail", " , app , Activity ");
Intent[] intents = {mainIntent, detailIntent};
context.startActivities(intents);
}else {
// app , app, DetailActivity Intent ,
//SplashActivity MainActivity, app , MainActivity // DetailActivity
Log.i("NotificationReceiver", "the app process is dead");
Intent launchIntent = context.getPackageManager().
getLaunchIntentForPackage("com.liangzili.notificationlaunch");
launchIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Bundle args = new Bundle();
args.putString("name", " ");
args.putString("price", "58 ");
args.putString("detail", " , app , Activity ");
launchIntent.putExtra(Constants.EXTRA_BUNDLE, args);
context.startActivity(launchIntent);
}
}
}
SplashActivity.java
SplashActivity.JAvaはまずappが起動した画像で、3 s後にMainActivityに入り、SplashActivityを起動したIntentにパラメータがついている場合はパラメータを取り出し、MainActivityを起動したIntentに入れる
public class SplashActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
// ActionBar
getSupportActionBar().hide();
// handler 3 MainActivity
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
// app Intent , app
// , MainActivity
if(getIntent().getBundleExtra(Constants.EXTRA_BUNDLE) != null){
intent.putExtra(Constants.EXTRA_BUNDLE,
getIntent().getBundleExtra(Constants.EXTRA_BUNDLE));
}
startActivity(intent);
finish();
}
}, 3000);
}
}
MainActivity.java
MainActivityでは、パラメータ入力がある場合は初期化終了後、パラメータに従ってDetailActivityを起動し、パラメータ入力がない場合は自分のタスクを終了します
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, PushService.class);
startService(intent);
setTitle("MainActivity");
Bundle bundle = getIntent().getBundleExtra(Constants.EXTRA_BUNDLE);
if(bundle != null){
// bundle , , DetailActivity
String name = bundle.getString("name");
String price = bundle.getString("price");
String detail = bundle.getString("detail");
SystemUtils.startDetailActivity(this, name, price, detail);
Log.i(TAG, "launchParam exists, redirect to DetailActivity");
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
DetailActivity.java
入力パラメータを表示すると簡単です.-D
public class DetailActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
getSupportActionBar().setTitle("DetailActivity");
String name = getIntent().getStringExtra("name");
String price = getIntent().getStringExtra("price");
String detail = getIntent().getStringExtra("detail");
((TextView)findViewById(R.id.name)).setText(name);
((TextView)findViewById(R.id.price)).setText(price);
((TextView)findViewById(R.id.detail)).setText(detail);
}
}
効果の表示
http://v.youku.com/v_show/id_XMTMwMjgyNTUwMA==.html?from=y1.7-1.2
demoダウンロード
https://github.com/slimhippo/androidcode