关于Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED

本文介绍了一个简单的绘图应用开发过程,使用Android平台进行实践。应用通过触摸事件捕捉用户绘制的动作,并利用Bitmap和Canvas实现了基本的绘图功能。此外,还介绍了如何保存绘制的内容到本地并通知系统更新图库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.itheima.paint;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private ImageView iv;
	private Bitmap baseBitmap;
	private Canvas canvas;//创建一个画布
	private Paint paint;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		iv=(ImageView) findViewById(R.id.iv);
		paint=new Paint();//创建一个画笔
		paint.setStrokeWidth(6);//设置画笔的宽度
		paint.setColor(Color.RED);//设置画笔的颜色
		
		
		//创建一个可以被修改的bitmap					
		baseBitmap=Bitmap.createBitmap(288, 327, Bitmap.Config.ARGB_8888);//前两个参数分别为宽度和高度   
		System.out.println("宽度:"+iv.getWidth());
		System.out.println("高度:"+iv.getHeight());
		canvas=new Canvas(baseBitmap);//以 baseBitmap 为基准创建一个画布
		canvas.drawColor(Color.WHITE);//给画布设定颜色
		
		//知道用户手指在屏幕上移动的轨迹
		iv.setOnTouchListener(new OnTouchListener() {
			//获取手指开始的坐标
			int startX;
			int startY;
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					System.out.println("手指按下");
					
					startX=(int) event.getX();
					startY=(int) event.getY();				
					break;
					
				case MotionEvent.ACTION_MOVE:
					System.out.println("手指移动");
					int newX=(int) event.getX();
					int newY=(int) event.getY();
					
					canvas.drawLine(startX, startY, newX, newY, paint);
					//重新更新画笔的开始位置、
					startX=(int) event.getX();
					startY=(int) event.getY();
					iv.setImageBitmap(baseBitmap);
					break;
				default:
					break;
				}
								
				return true;//如果想要onTouch这个事件不停地执行 应该将此返回值设置为true
			}
		});
	}

	public void save(View view){
		try {
			String fileName=System.currentTimeMillis()+".jpg";//保存图片的名称
			File file=new File(Environment.getExternalStorageDirectory(),fileName);
			FileOutputStream outstream=new FileOutputStream(file);
			baseBitmap.compress(CompressFormat.JPEG, 100, outstream);
			outstream.close();
			Toast.makeText(this,"保存图片成功",1).show();
			
			//模拟一个消息通知系统SD卡被重新挂载了   目的是为了让图库加载刚刚保存的图片
			
			//MediaScannerConnection.scanFile(Context context, String[] paths, String[] mimeTypes,OnScanCompletedListener callback)
			//这是一个静态方法,使用就比较简单了。OnScanCompletedListener  可实现可不实现,
			//它只有一个方法,在扫描完成的时候回调。scanFile 静态方法可以一次传递多个文件,
			//如果 mimeTypes 不为空,就必须于 paths 的长度一致。mimeTypes 可以为空。
			
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){//如果是4.4及以上版本
				//安卓4.4及以上版本 使用
				MediaScannerConnection.scanFile(this, 
						new String[]{Environment.getExternalStorageDirectory() + "/" + fileName},
						null, null);//共四个参数
			}else{
				//注意以下方法只能在  安卓4.4之前(不包括安卓4.4) 使用
				Intent intent= new Intent();
				intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
				intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
				sendBroadcast(intent);
			}
		
		} catch (Exception e) {
			Toast.makeText(this,"保存图片失败",1).show();
			e.printStackTrace();
		}
	}
	
}

<think>好的,我现在需要解决用户遇到的Java中的java.lang.SecurityException: Permission Denial问题,特别是启动Activity时出现的未导出错误。用户提到报错信息显示Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] ... },并且指出Activity未导出,导致权限拒绝。 首先,我得回忆一下Android的组件导出规则。根据Android的安全机制,Activity、Service、Receiver等组件如果设置了android:exported="false",则其他应用无法直接启动它们,除非有相同的签名或权限。用户的情况是尝试从一个不同的UID(用户ID)启动未导出的Activity,所以系统阻止了这个操作,抛出了SecurityException。 查看用户提供的引用[1]和[4],错误信息明确提到Activity未导出,这可能是因为在AndroidManifest.xml中该Activity的exported属性被显式设置为false,或者默认情况下未满足导出的条件。例如,如果Activity没有声明任何intent-filter,默认exported是false;如果有intent-filter,则默认是true。但用户的Activity显然有MAIN和LAUNCHER的intent-filter,所以默认应该是导出的。但可能开发者在代码中显式设置了exported为false,或者某些配置覆盖了默认行为。 接下来,根据引用[2],SecurityException通常由安全管理器检测到违反安全策略的操作引起。在这种情况下,尝试启动未导出的Activity属于权限问题,因此需要检查组件导出设置。 解决方案方面,首先需要检查AndroidManifest.xml中目标Activity的声明。确保该Activity的android:exported属性设置为true,或者至少没有显式设置为false。同时,如果有必要,可能需要添加相应的权限声明,比如使用android:permission属性来限制调用者,但这也需要调用方拥有该权限。 用户可能是在使用像Appium这样的测试工具时遇到这个问题,如引用[3]提到的,处理权限错误时需要确保被测试的Activity是导出的。如果是测试环境,临时将Activity导出可能是一个解决办法,但要注意生产环境中不应随意导出组件,以免带来安全风险。 此外,用户可能需要检查Intent的构造是否正确,比如是否明确指定了ComponentName,或者是否有其他方式错误地触发了跨应用启动。如果是应用内部启动,可能需要检查是否使用了正确的Context或是否有其他权限问题。 另外,如果该Activity确实是应用的入口(LAUNCHER),通常应该导出,所以可能用户的配置有误。需要确认是否存在多个LAUNCHER Activity导致冲突,或者是否有其他配置错误。 最后,总结可能的解决步骤:检查并修改AndroidManifest.xml中的exported属性,确保Activity导出;检查权限设置;如果是测试环境,临时导出并添加tools:ignore="ExportedActivity"来忽略lint警告;处理Intent的启动方式是否正确等。</think>### 解决Java中Permission Denial的安全异常问题 #### 问题分析 当出现`java.lang.SecurityException: Permission Denial`异常时,通常是因为尝试启动的Activity未在`AndroidManifest.xml`中声明为导出(`android:exported="true"`)[^1][^4]。Android系统默认对未导出的组件禁止跨应用访问,以防止恶意调用[^2]。 #### 解决步骤 1. **检查目标Activity的导出属性** 在`AndroidManifest.xml`中确认目标Activity是否包含以下配置: ```xml <activity android:name=".ui.LoginActivity" android:exported="true" <!-- 确保为true --> android:permission="..." > <!-- 可选:添加权限限制 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ``` - 若未显式声明`android:exported`,系统会根据`<intent-filter>`自动推导: - **有`<intent-filter>`**:默认`exported="true"` - **无`<intent-filter>`**:默认`exported="false"` 2. **处理测试环境需求** 若为自动化测试(如Appium),可临时添加导出属性并忽略安全警告: ```xml <activity android:name=".ui.LoginActivity" android:exported="true" tools:ignore="ExportedActivity" /> ``` 但需确保生产环境中移除此配置[^3]。 3. **检查调用方权限** 若目标Activity声明了`android:permission`属性,调用方需在`An
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值