您的位置:首页 > 移动开发

android中两个app之间利用广播互相监听

2016-05-25 16:15 393 查看
今天去面试,什么公司就不谈了,技术官直接就上需求让我思考一下,自己就写了一个小demo,效果还可以,奉献一下,源码要的邮箱,我就不上传了。

按照惯例先贴出需求:

需求:

1.apk2终止时发送广播,apk1接受,然后启动apk2。

2.主动:当apk2被卸载后,apk1查询是否卸载,然后安装apk2。

3.被动:apk2当应用被卸载后,系统发出广播,apk1接受判断后安装apk2。

自己做了一个demo,效果如下:

1.安装test1后,点击button,开始检测test2,查的没有test2,开始下载。

2.下载test2后,退出test2,提示4秒后开启test2,test2开启。

3.卸载test2,提示test1已卸载,然后4秒后重装test2。

test1项目结构:



test2项目结构:



一,test1部分

MainActivity的代码如下:

public class MainActivity extends Activity implements OnClickListener,BRInteraction {

private Button app1Btn;
private MyReceiver myReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initBroadcastReciver();
setListener();
}

------------------------------------------------------------

//初始化broadcastreceiver
private void initBroadcastReciver() {
IntentFilter intentFilter1 = new IntentFilter();
intentFilter1.addAction("app2isclosed");
IntentFilter intentFilter2 = new IntentFilter();                                  intentFilter2.addAction("android.intent.action.PACKAGE_REMOVED");
intentFilter2.addDataScheme("package");
myReceiver = new MyReceiver();
registerReceiver(myReceiver, intentFilter1);
registerReceiver(myReceiver, intentFilter2);
}

//初始化view
private void initViews() {
app1Btn = (Button) findViewById(R.id.app1_btn);
}

//设置监听
private void setListener() {
app1Btn.setOnClickListener(this);
myReceiver.setBRInteractionListener(this);
}

--------------------------------------------------

@Override
public void onClick(View v) {

switch (v.getId()) {
case R.id.app1_btn:
switchApp2();
break;
default:
break;
}
}

//启动app2,如果没有开始下载
public void switchApp2() {
if (hasApplication()) {
ComponentName componetName = new ComponentName(
// 这个是另外一个应用程序的包名
"com.example.test2",
// 这个参数是要启动的Activity
"com.example.test2.MainActivity");
Intent intent = new Intent();
intent.setComponent(componetName);
startActivity(intent);
} else {
Toast.makeText(MainActivity.this, "没有安装test2,正在安装", Toast.LENGTH_LONG)
.show();
installApk();
}
}

//下载app2
@Override
public void installApk() {
new Handler().postDelayed(new Runnable() {
public void run() {
slientInstall(); // 未安装进行安装
}
}, 2 * 1000);
}

//判断是否存在test2
public boolean hasApplication() {
PackageManager packageManager = getPackageManager();
// 查询是否有该Intent的Activity
Intent in = new Intent();
in.setClassName("com.example.test2", "com.example.test2.MainActivity");
List<ResolveInfo> activities = packageManager.queryIntentActivities(in,
0);
Log.i("----tag-----", "activities" + activities.size());
// activities里面不为空就有,否则就没有
return activities.size() > 0 ? true : false;
}

//当接受到app2发送的广播,回调
@Override
public void app2IsClosedcallBack(String content) {
Log.i("-----tag------", "content:" + content);
new Handler().postDelayed(new Runnable() {
public void run() {
switchApp2();
}
}, 4 * 1000);

}

/*----------------------安装apk2---------------------*/

/**
* 静默安装
*
* @param file
* @return
*/
public boolean slientInstall() {
createFile(); // 进行资源的转移 将assets下的文件转移到可读写文件目录下
File file = new File(Environment.getExternalStorageDirectory()
.getPath() + "/temp.apk");

boolean result = false;
Process process = null;
OutputStream out = null;
System.out.println(file.getPath());
if (file.exists()) {
System.out.println(file.getPath() + "==");
try {
process = Runtime.getRuntime().exec("su");
out = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(out);
dataOutputStream.writeBytes("chmod 777 " + file.getPath()

e989
+ "\n"); // 获取文件所有权限
dataOutputStream
.writeBytes("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install -r "
+ file.getPath()); // 进行静默安装命令
// 提交命令
dataOutputStream.flush();
// 关闭流操作
dataOutputStream.close();
out.close();
int value = process.waitFor();

// 代表成功
if (value == 0) {
Log.e("hao", "安装成功!");
result = true;
} else if (value == 1) { // 失败
Log.e("hao", "安装失败!");
result = false;
} else { // 未知情况
Log.e("hao", "未知情况!");
result = false;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!result) {
Log.e("hao", "root权限获取失败,将进行普通安装");
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
startActivity(intent);
result = true;
}
}

return result;
}

public void createFile() {
InputStream is = null;
FileOutputStream fos = null;
try {
is = MainActivity.this.getAssets().open("test2.apk");
File file = new File(Environment.getExternalStorageDirectory()
.getPath() + "/temp.apk");
file.createNewFile();
fos = new FileOutputStream(file);
byte[] temp = new byte[1024];
int i = 0;
while ((i = is.read(temp)) > 0) {
fos.write(temp, 0, i);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(myReceiver);
}
}


MyReceiver的代码如下:

/**
*
* @ClassName: MyReceiver
* @Description:用来检测APP2和系统的广播
* @author guang.hu
* @date 2016年5月25日 上午11:16:55
*
*
*/
public class MyReceiver extends BroadcastReceiver{

private BRInteraction brInteraction;

@Override
public void onReceive(Context context, Intent intent) {

//app2关闭时,这里接受广播
if(intent.getAction().equals("app2isclosed")){
String name = intent.getExtras().getString("name");
Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
brInteraction.app2IsClosedcallBack(name);
}

//当有程序卸载时,系统发送广播,这里接受
if(intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
String packageName = intent.getDataString();           if(packageName.equals("package:com.example.test2")){

Toast.makeText(context, "app2已卸载,正在重装", Toast.LENGTH_SHORT).show();

brInteraction.app2IsClosedcallBack("app2已卸载,正在重装");
}
}
}

----------------------------------------

//自定义接口实现对app2退出的处理,卸载app2后的处理
public interface BRInteraction {
public void app2IsClosedcallBack(String content);

}

----------------------------------------

public void setBRInteractionListener(BRInteraction brInteraction) {
this.brInteraction = brInteraction;
}

}


xml文件配置如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test1"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>

</manifest>


二,test2部分

public class MainActivity extends Activity implements OnClickListener {

private Button app2Btn;

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

private void initViews() {
app2Btn = (Button) findViewById(R.id.app2_btn);
}

private void setListener() {
app2Btn.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.app2_btn:
switchApp1();
break;

default:
break;
}
}

//启动app1
public void switchApp1() {
if (hasApplication()) {
ComponentName componetName = new ComponentName(
// 这个是另外一个应用程序的包名
"com.example.test1",
// 这个参数是要启动的Activity
"com.example.test1.MainActivity");
Intent intent = new Intent();
intent.setComponent(componetName);
startActivity(intent);

} else {
Toast.makeText(MainActivity.this, "没有安装test1", Toast.LENGTH_LONG)
.show();
}
}

//当程序中终止时,发送广播
private void mySendBroadcast() {
Intent intent = new Intent();
intent.setAction("app2isclosed");
intent.putExtra("name", "app2 is closed,4秒后重启");
MainActivity.this.sendBroadcast(intent);
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
mySendBroadcast();
}

//判断是否存在test1
public boolean hasApplication() {
PackageManager packageManager = getPackageManager();
// 查询是否有该Intent的Activity
Intent in = new Intent();
in.setClassName("com.example.test1", "com.example.test1.MainActivity");
List<ResolveInfo> activities = packageManager.queryIntentActivities(in,
0);
Log.i("----tag-----", "activities" + activities.size());
// activities里面不为空就有,否则就没有
return activities.size() > 0 ? true : false;
}

}


xml文件配置如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test2"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTask"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  app 需求 技术