在一个应用程序(App1)中,我正在播放一条消息。以下代码是正确的 - >如果我尝试在同一个项目中播放广播,则会检测到广播。
sendBroadcast(new Intent("com.example.MESSAGE_INTENT").putExtra("MESSAGE", ((EditText) findViewById(R.id.textField)).getText()));
我创建的App2有一个BroadcastReceiver
,等待广播的Intent
,但方法onReceive
永远不会被调用。
如何更改BroadcastReceiver
应用以使服务始终在后台运行?
App2清单和代码:
package com.example;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("WORKS" , "!!!!!!!!!!");
Toast.makeText(context, "CAUGHTt\n" + intent.getExtras().getString("MESSAGE"), Toast.LENGTH_LONG).show();
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jjoe64" >
<permission-group
android:name="com.examples.my_permissions"
android:label="my permissions groupd" />
<permission
android:name="com.examples.my_permissions.MY_PERMISSION"
android:label="my permission"
android:permissionGroup="com.examples.my_permissions" />
<application>
<receiver
android:name="MyReceiver"
android:exported="true"
android:permission="com.examples.my_permissions.MY_PERMISSION" >
<intent-filter>
<action android:name="com.example.MESSAGE_INTENT" />
</intent-filter>
</receiver>
<service android:name="BackgroundService" />
</application>
</manifest>
播音员MANIFEST
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"
android:exported="true" >
<uses-permission android:name="com.examples.my_permissions.MY_PERMISSION" />
<permission-group
android:name="com.examples.my_permissions"
android:label="my permissions groupd" />
<permission
android:name="com.examples.my_permissions.MY_PERMISSION"
android:label="my permission"
android:permissionGroup="com.examples.my_permissions" />
<application>
<receiver
android:name="com.example.MyReceiver"
android:exported="true"
android:permission="com.examples.my_permissions.MY_PERMISSION" >
<intent-filter>
<action android:name="com.example.MESSAGE_INTENT" />
<action android:name="android.intent.action.AIRPLANE_MODE" />
</intent-filter>
</receiver>
</application>
</manifest>
MAJOR EDIT
我创建了另一个MainActivity
的应用程序,我创建了final BroadcastReceiver
:
CODE:
package com.example.receiver2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
final BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("WORKS" , "!!!!!!!!!!");
Toast.makeText(context, "CAUGHTt\n" + intent.getExtras().getString("MESSAGE"), Toast.LENGTH_LONG).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.receiver2"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="com.examples.my_permissions.MY_PERMISSION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<permission-group
android:name="com.examples.my_permissions"
android:label="my permissions groupd" />
<permission
android:name="com.examples.my_permissions.MY_PERMISSION"
android:label="my permission"
android:permissionGroup="com.examples.my_permissions" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver
android:name="com.example.MyReceiver"
android:exported="true" >
<intent-filter>
<action android:name="com.example.MESSAGE_INTENT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="com.example.receiver2.MainActivity"
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>
但我得到了一个例外:
04-18 10:16:46.332: E/AndroidRuntime(1244): FATAL EXCEPTION: main
04-18 10:16:46.332: E/AndroidRuntime(1244): Process: com.example.receiver2, PID: 1244
04-18 10:16:46.332: E/AndroidRuntime(1244): java.lang.RuntimeException: Unable to instantiate receiver com.example.MyReceiver: java.lang.ClassNotFoundException: Didn't find class "com.example.MyReceiver" on path: DexPathList[[zip file "/data/app/com.example.receiver2-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.example.receiver2-1, /system/lib]]
04-18 10:16:46.332: E/AndroidRuntime(1244): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2400)
答案 0 :(得分:4)
如果它有帮助,我会组建一个非常快速的演示应用程序(对于Eclipse),它包含一个导出的,不安全的BroadcastReceiver
,您可以将其用作模板。我已将其存储在我的github帐户中:
您可以使用它来遵循我的答案第3步中给出的建议,第2步,我建议您使用简单的导出BroadcastReceiver
。
我确信一旦你完成并运行,其余的过程将非常简单。
您可以通过两种不同的方式声明BroadcastReceiver
:
MainActivity
)在另一个类中声明时,您需要使用方法ContextWrapper.registerReceiver()
和ContextWrapper.unregisterReceiver()
来注册意图。您的代码需要执行此操作,因此您的应用必须正在运行才能接收广播。
如果您想通过广播“唤醒”您的应用,那就是您在清单中声明接收器(就像您所做的那样)。在这种情况下,您的BroadcastReceiver
将是一个单独的类文件:
package mobiric.demo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* Must be declared in the manifest.
*/
public class MobiricReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// do something
}
}
看起来你正在混合这两种技术。我认为你需要第二种技术:
我现在能想到的最后一件事是,我认为您需要在系统允许BroadcastReceiver
工作之前手动启动您的应用。
因此,请务必在测试前在应用中启动任何Activity
。
以下是关于此的博文:
哦等等 - 你没有在你的清单中宣布<uses-permission android:name="com.examples.my_permissions.MY_PERMISSION" />
。
但我通常希望logcat告诉你,你有权限问题。
对于它的价值,我会将这个问题分解为几个步骤:
通过这种方式,您可以隔离潜在的问题,因此您一次只能处理一个棘手的问题。它可以更容易地专注于问题,而无需追踪其他可能性。
此外,通过在开发时删除自定义权限,您可以使用ADB来测试接收器,这可以节省大量时间。在这里查看adb shell am broadcast ...
的详细信息:
原始问题已更新为exported="true"
。
使用自定义权限需要使用相同的签名密钥对两个应用进行签名。
然而我过去遇到过未解决的“自定义权限”问题。基本上我的新自定义权限未在设备上授予。卸载并重新安装应用程序没有任何区别 - 系统似乎将自定义权限存储在我无法更新的地方。
以下是此论坛上的相关帖子 - 遗憾的是我无法解决此问题,并且不得不接受提供的解决方法:
您需要通过将BroadcastReceiver
放入接收者的清单声明中来“导出”您的exported="true"
。
请参阅以下更改:
<receiver
android:name="MyReceiver"
android:permission="com.examples.my_permissions.MY_PERMISSION"
android:exported="true" >
<intent-filter>
<action android:name="com.example.MESSAGE_INTENT" />
</intent-filter>
</receiver>
注意:此答案的未来读者,请注意原帖包含permission
。这可以防止出现安全问题,并要求使用相同的签名对呼叫应用进行签名。