我正在开发一个应用程序,必须在通话时启动小部件。
我已经在清单中注册了广播请求,例如:
java2s
我已经在清单中注册了我的广播接收器,
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Main {
private static void runSonic(
AudioInputStream audioStream,
SourceDataLine line,
float speed,
float pitch,
float rate,
float volume,
boolean emulateChordPitch,
int quality,
int sampleRate,
int numChannels) throws IOException {
Sonic sonic = new Sonic(sampleRate, numChannels);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int bufferSize = line.getBufferSize();
byte inBuffer[] = new byte[bufferSize];
byte outBuffer[] = new byte[bufferSize];
int numRead, numWritten;
sonic.setSpeed(speed);
sonic.setPitch(pitch);
sonic.setRate(rate);
sonic.setVolume(volume);
sonic.setChordPitch(emulateChordPitch);
sonic.setQuality(quality);
do {
numRead = audioStream.read(inBuffer, 0, bufferSize);
if (numRead <= 0) {
sonic.flushStream();
} else {
sonic.writeBytesToStream(inBuffer, numRead);
}
do {
numWritten = sonic.readBytesFromStream(outBuffer, bufferSize);
if (numWritten > 0) {
line.write(outBuffer, 0, numWritten);
byteArrayOutputStream.write(outBuffer, 0, numWritten);
}
} while (numWritten > 0);
} while (numRead > 0);
byte audioBytes[] = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(audioBytes);
AudioFormat format = line.getFormat();
AudioInputStream audioInputStream = new AudioInputStream(byteArrayInputStream, format, audioBytes.length / format.getFrameSize());
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, new File("C:\\audio2.wav"));
}
public static void main(String[] argv) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
float speed = 1.0f;
float pitch = 1.0f;
float rate = 1.5f;
float volume = 1.0f;
boolean emulateChordPitch = false;
int quality = 0;
AudioInputStream stream = AudioSystem.getAudioInputStream(new File("C:\\audio1.wav"));
AudioFormat format = stream.getFormat();
int sampleRate = (int) format.getSampleRate();
int numChannels = format.getChannels();
SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format,
((int) stream.getFrameLength() * format.getFrameSize()));
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
line.open(stream.getFormat());
line.start();
runSonic(stream, line, speed, pitch, rate, volume, emulateChordPitch, quality,
sampleRate, numChannels);
line.drain();
line.stop();
}
}
注意:当用户按下按钮时,我将在运行时启用接收器。那也是我的测试系统正在运行Android 7.0时要求烫发的时间
然后我在运行时按如下按钮请求权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
...Other permissions required for screen overlay...
我等待许可请求的结果,
<receiver android:name=".phoneReceiver"
android:exported="true"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
在 btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_PHONE_STATE}, 2);
showToast(getApplicationContext(), "Phone state requested");
} else{
enableWidget(); //if permissions are already granted
}
}
});
中,我这样启用广播接收器:
@Override
public void onRequestPermissionsResult(int req, @NonNull String[] perms, @NonNull int[] results){
switch(req){
case 2:
if(results.length > 0 && results[0]==PackageManager.PERMISSION_GRANTED){
showToast(this, "Phone state granted");
enableWidget();
}
return;
}
}
现在,根据我的看法,只要状态改变但这种情况不会发生,就应该调用接收器。相反,我在logcat中得到以下内容,这使我认为接收器已启用,但仍未调用。
enableWidget()
我在这里想念什么?
PS 这是我的接收器的摘要,减去不必要的内容:
private void enableWidget(){
PackageManager pm = MainActivity.this.getPackageManager();
ComponentName comp = new ComponentName(getApplicationContext(), phoneReceiver.class);
pm.setComponentEnabledSetting(comp, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
PPS 我在系统设置中检查了应用程序权限,并且“电话”设置为打开。
我尝试通过在清单中将接收器声明为默认方式来保持默认情况下启用接收器:
W/BroadcastQueue: Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } to com.example.myapplication/.phoneReceiver requires android.permission.READ_PRIVILEGED_PHONE_STATE due to sender android (uid 1000)
,并删除用于在运行时启用窗口小部件的部分。我仍然在运行时请求权限。我仍然遇到相同的错误。
使用API级别22的同一系统。
答案 0 :(得分:1)
清单上声明的接收者::如果您的应用定位到API级别26或更高级别,则不能使用清单来声明隐式广播的接收者(不针对广播的广播) (特别是您的应用)),但一些不受此限制Exempted List限制的隐式广播除外。在大多数情况下,您可以使用计划的作业。
上下文注册的接收器::只要广播的注册上下文有效,就接收广播。例如,如果您在Activity上下文中注册,则只要该活动未销毁,您就会收到广播。如果您在“应用程序”上下文中注册,则只要该应用程序正在运行,您就会收到广播。
由于内存改进,请检查official site以获得更多详细信息。
答案 1 :(得分:-1)
您可以使用JobScheduler API触发事件,当我为自己的一个APP使用Geofencing API时,我遇到了类似的问题