精华内容
下载资源
问答
  • 易语言软件自动下载更新源码,软件自动下载更新,交互回调函数
  • Android软件自动更新升级(自动下载安装新版本)-附件资源
  • 资源介绍: 源码利用易语言网络传送支持库和压缩解压支持库,实现软件自动下载更新包,自动删除旧版本,自动运行新版本功能。 资源作者:
  • 自动更新软件

    2017-04-18 15:45:16
    内容【欢迎使用!...文件名:版本更新系统.rar; 下载地址:http://ys-g.ys168.com/579185498/n2J6J4K5I7LHLVHgMhK/%E6%96%90%E8%AE%AFK2%E6%8D%A2IP%E4%B8%93%E7%94%A8%E7%89%88%20%20By%EF%BC%9A%E5%A4%A9%E

    自动更新

    内容【欢迎使用!】

    限制:0;
    当前版本:1.0-
    最新版本;1.0-
    文件名:版本更新系统.rar;
    下载地址:http://ys-g.ys168.com/579185498/n2J6J4K5I7LHLVHgMhK/%E6%96%90%E8%AE%AFK2%E6%8D%A2IP%E4%B8%93%E7%94%A8%E7%89%88%20%20By%EF%BC%9A%E5%A4%A9%E6%88%901.2.rar|
    更新说明【123456
    【结束】
    展开全文
  • 铭美智能自动更新软件是一款功能强大的软件自动更新助手。怎么设定软件自动升级?铭美智能自动更新软件(软件自动升级工具)轻松帮助用户。可以根据自定义的配置文件,对windows软件进行更新或者修复,避免更新程序的...
  • 易语言软件自动更新源码,软件自动更新,下载子程序,取中间文本项,HTTP进度下载,进度显示,InternetGetConnectedState,InternetOpenA,InternetOpenUrlA,HttpQueryInfoA,InternetCloseHandle,InternetReadFile,...
  • C#软件自动更新

    2018-01-02 10:50:22
    我做过ftp自动更新的,就是在本地的配置文件放置一个版本号,然后服务器有一个配置文件还有要更新的文件,在客户端的程序启动时通过ftp将服务器端的配置文件下载到本地,然后进行版本比较,如果服务器版本高于本地...
  • 启用自动更新允许您的设备后台自动安装的所有更新软件,而无需手动下载最新的软件版本。默认情况下macOS并未启动自动更新,如果您想在苹果电脑上拥有此功能,可以通过简单的设置来实现。注意 新版本的系统会小概率...

    启用自动更新已经成为每一个操作系统的默认行为,无论是windows,macos还是linux等等。启用自动更新允许您的设备后台自动安装的所有更新软件,而无需手动下载最新的软件版本。默认情况下macOS并未启动自动更新,如果您想在苹果电脑上拥有此功能,可以通过简单的设置来实现。

    注意

    新版本的系统会小概率导致应用程序崩溃。作为预防措施,您最好定期备份您的重要文档,以防系统自动修复导致文件丢失。

    按照以下步骤就可以启用自动更新:

    1. 通过单击左上角的苹果图标并在弹出的菜单选择“系统偏好设置”来打开系统偏好设置工具。

    a1db42ab09ec3e2e0f48c9aee2db1995.png

    2. 选择“软件更新”,进入软件更新界面。

    f8399e63603cffbcc5e45e82c55480e7.png

    3. 启用“自动保持我的mac最新”选项。为你的mac启用自动更新功能。

    如果你点击“高级”按钮,你会看到一系列自动更新的选项。下面简要介绍一下这些选项。

    95737abf0047d96991991d47d231dfc9.png

    下载可用的更新:默认情况下已经启用,苹果电脑会自动在后台下载所有更新,并让您知道它们何时可以安装。如果禁用此选项,您将会收到更新可用的通知但不会自动下载,这在你使用手机移动网络的时候非常有用,因为那样会产生高额的费用,wifi或有线网络可以随意。

    安装macOS更新:启用此选项将使您的苹果电脑自动安装更新。默认情况下,此选项未启用。

    安装系统数据文件和安全更新:默认情况下启用此选项。它允许重要的安全更新一旦可用就优先安装在您的Mac上,因此启用它是一个不错的选择。

    请记住,如果您想要启用/禁用上面列出的任何选项,您将需要您的管理员密码。您也可以选择延迟操作系统更新。此外,当您不使用机器时,操作系统更新也可以由macOS在深夜安装。当您工作时,通知中会弹出一个选项来安装更新,但您可以暂停安装,并在晚上安装更新。

    展开全文
  • 今天花了不少功夫,终于把软件自动更新功能实现了,还是做一下笔记吧! 第一步:  获取服务器当前最新版本号信息,与当前应用版本号进行对比。这个过程我不多讲,我从第二步开始说。也就是确认当前版本低于服务器...

    今天花了不少功夫,终于把软件自动更新功能实现了,还是做一下笔记吧。自己把代码整理了一下,做了一个很简单的Demo。


    首先是效果图:

    点击第一个按钮会调用系统浏览器默认的下载功能,这个用起来很方便,但是不太友好。

    点击第二个安妮会开启服务下载文件,这个功能需要在AndroidManifest.xml提前添加权限:

        <!-- 允许访问网络权限 -->
        <uses-permission android:name="android.permission.INTERNET" />
        <!-- 读写外部存储卡 -->
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    主界面效果。

    点击下载按钮,状态栏弹出状态栏下载提示,开始下载文件。


    软件下载过程,状态栏一直显示下载进度。


    软件下载成功,会自动跳出安装界面。




    好了,效果图完毕,接下来直接上代码:
    MainActivity代码内容:
    /**
     * 开启服务下载文件并在状态栏显示下载进度
     * @author SHI
     * 2016年3月17日 13:47:41
     */
    public class MainActivity extends Activity{
    
    	/**文件下载地址**/
    	private String addressOfApkDownload = "http://115.28.9.25//DaiNiFei.apk";
    	/**使用系统浏览器下载**/
    	private Button btn_downloadBySys;
    	/**开启服务下载**/
    	private Button btn_downloadBySelf;
    	
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            btn_downloadBySys = (Button) findViewById(R.id.btn_downloadBySys);
            btn_downloadBySelf = (Button) findViewById(R.id.btn_downloadBySelf);
            
            btn_downloadBySys.setOnClickListener(new View.OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				//调用系统自带浏览器下载
    				Uri uri = Uri.parse(addressOfApkDownload);  
    				Intent downloadIntent = new Intent(Intent.ACTION_VIEW, uri);  
    				startActivity(downloadIntent); 				
    			}
    		});
            
            btn_downloadBySelf.setOnClickListener(new View.OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				//开启服务下载
    				Intent intent = new Intent(MainActivity.this, UpdateAppService.class);
    				intent.putExtra("addressOfApkDownload", addressOfApkDownload);
    				startService(intent);
    			}
    		});
    
    
        }
        
        
    }

    activity_main.xml布局文件内容:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical" >
    
        <Button
            android:id="@+id/btn_downloadBySys"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="使用系统浏览器下载文件" />
    
        <Button
            android:id="@+id/btn_downloadBySelf"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="开启服务下载文件" />
    
    </LinearLayout>

    对应的更新下载服务UpdateAppService代码:
    /***
     * 更新下載服务
     * @author SHI
     * 2016-3-16 19:57:09
     */
    public class UpdateAppService extends Service {
    	//和下载过程状态栏的显示有关类               主要是在手机状态栏上显示和更新当前下载进度  
    	//这几个类具体什么功能,可以自己详细在网上搜一下。
    	/**远程View 显示在状态栏的内容**/
    	private RemoteViews contentView;
    	/**状态栏内容的管理类**/
    	private NotificationManager notiManage;
    	/**状态栏类**/
    	private Notification note;
    	/**设备上下文**/
    	private Context mContext;
    	
        private int Notification_ID = 110;
    	private PendingIntent pd;
    	
    	UpdateAppServiceController updateAppServiceControllerImp;
        
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		if(mContext == null){
    			mContext = this;
    			updateAppServiceControllerImp = new UpdateAppServiceController(this);
    			updateAppServiceControllerImp.init(intent);
    		}
    		return super.onStartCommand(intent, flags, startId);
    	}
    
    	
    	public void initView(Intent intent) {
    		
    			notiManage=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
    			
    			note=new Notification();
    	
    			note.icon=R.drawable.ic_launcher;
    			
    			note.tickerText = "软件更新包下载";
    	
    			note.flags=Notification.FLAG_AUTO_CANCEL;
    	
    			contentView = new RemoteViews(getPackageName(), R.layout.layout_progress); 
    	
    			contentView.setProgressBar(R.id.notificationProgress, 100, 0, false); 
    	
    			note.contentView = contentView;
    			
    			notiManage.notify(Notification_ID, note);
    	}
    	
    	/***
    	 * 显示下载进度
    	 * @param progress
    	 */
    	public void showLoading(long total, long current) {
    		int progress = (int) (current*100/total);
    		note.contentView.setProgressBar(R.id.notificationProgress, 100, progress, false);
    		note.contentView.setTextViewText(R.id.notificationPercent, "已下载"+progress+"%"); 				
    		note.contentIntent = pd;
    		notiManage.notify(Notification_ID, note);
    	}
    	
    	/***
    	 * 显示错误信息
    	 * @param msg
    	 */
    	public void showFialedMsg(String msg){
    		ToastUtil.show(mContext, msg);
    	}
    	
    	/***
    	 * 下载成功
    	 */
    	public void finishRefrushView(String locationForApkDown){
    		note.contentView.setProgressBar(R.id.notificationProgress, 100, 100, false); 					
    		note.contentView.setTextViewText(R.id.notificationPercent, "已下载完成"); 
    		note.contentIntent=pd;		
    		//点击安装
    		Intent intent = new Intent(Intent.ACTION_VIEW);
    		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    		intent.setDataAndType(Uri.parse("file://" + locationForApkDown),"application/vnd.android.package-archive");
    //		intent.setDataAndType(Uri.fromFile(responseInfo.result), "application/vnd.android.package-archive");
    
    		pd = PendingIntent.getActivity(mContext, 0, intent, 0);//这个非要不可。
    		
    		note.contentIntent = pd;
    		
    		notiManage.notify(Notification_ID, note);
    		startActivity(intent);	
    		stopSelf();
      	}
    	
    	
    	
    	@Override
    	public IBinder onBind(Intent intent) {
    		return null;
    	}
    
    	/**
    	 * 结束当前服务时  清空手机状态栏内容
    	 */
    	@Override
    	public void onDestroy() {
    		notiManage.cancel(Notification_ID);
    		super.onDestroy();
    	}
    
    }

    UpdateAppServiceController代码:

    /****
     * 业务逻辑控制层
     * @author SHI
     * 2016年3月16日 19:56:57
     */
    public class UpdateAppServiceController{
    
    	UpdateAppService mUpdateAppService;
    	private String name_App;
    	
    	
    	public UpdateAppServiceController(UpdateAppService mUpdateAppService) {
    		super();
    		this.mUpdateAppService = mUpdateAppService;
    	}
    
    	public void init(Intent intent) {
    		mUpdateAppService.initView(intent);
    		beginToUpdateApp(intent);
    	}
    	
    	public void beginToUpdateApp(Intent intent){
    		
    		//获取安装包下载地址
    		final String addressOfApkDownload = intent.getStringExtra("addressOfApkDownload");
    		//获取安装包名称    并获取下载SD卡位置
    		int position = addressOfApkDownload.lastIndexOf("/");
    		name_App = addressOfApkDownload.substring(position+1, addressOfApkDownload.length());
    		
    		final String locationForApkDown = SystemUtil.getDownloadFilePath(name_App);
    		HttpUtils httpUtils = new HttpUtils();
    		LogUtils.i("beginToUpdateApp");
    		/**
    		 * addressOfApkDownload 文件下载地址
    		 * locationForApkDown   文件下载到本地的路径
    		 * 为false的时候,每次下载都会把之前的文件覆盖掉重新下载,ture的时候,会先检测本地文件,如果存在,则抛出file has downloaded completely异常
    		 */
    		httpUtils.download(addressOfApkDownload, locationForApkDown, true, new RequestCallBack<File>() {
    			
    			@Override
    			public void onLoading(long total, long current, boolean isUploading) {
    				mUpdateAppService.showLoading(total,current);
    			}
    			
    			@Override
    			public void onSuccess(ResponseInfo<File> responseInfo) {
    				Log.i("下载结果", responseInfo.result.getAbsolutePath());
    				mUpdateAppService.finishRefrushView(locationForApkDown);
    				
    			}
    			@Override
    			public void onFailure(HttpException error, String msg) {
    				if(msg.contains("file has downloaded completely")){
    					mUpdateAppService.finishRefrushView(locationForApkDown);
    				}else{
    					mUpdateAppService.stopSelf();
    				}
    			}
    		});
    	}
    
    }



    其中用到的layout_progress.xml状态栏布局文件内容:
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="3dp" >
    
        <ImageView
            android:id="@+id/notificationImage"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginRight="10dp"
            android:layout_centerVertical="true"
            android:src="@drawable/ic_launcher" />
    
        <TextView
            android:id="@+id/notificationTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/notificationImage"
            android:text="软件更新包下载"
            android:textSize="18sp" />
    
        <ProgressBar
            android:id="@+id/notificationProgress"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/notificationTitle"
            android:layout_toRightOf="@+id/notificationImage" />
    
        <TextView
            android:id="@+id/notificationPercent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/notificationProgress"
            android:layout_toRightOf="@+id/notificationImage"
            android:text="已下载0%" /> 
    
    </RelativeLayout>

    工具类SystemUtil:

    /***
     * 系统工具类  获取  包管理器信息,SDcard信息,网络状况信息
     * @author SHI
     * 2016-2-25 16:39:55
     */
    public class SystemUtil {
    
    	/**获取当前应用版本号**/
    	public static int getCurrentAppVersionCode(Context mContext){
            // 获得包管理器,注意,整个android手机,共用一个包管理器
             PackageManager packageManager = mContext.getPackageManager();
    		 PackageInfo packageInfo = null;
    		try {
    			packageInfo = packageManager.getPackageInfo(mContext.getPackageName(), 0);
    		} catch (NameNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		if(packageInfo != null){
    			return packageInfo.versionCode;
    		}else{
    			return 0;
    		}
    	}
    	
    	/**获取当前应用版包名**/
    	public static String getCurrentAppVersionName(Context mContext){
    		// 获得包管理器,注意,整个android手机,共用一个包管理器
    		PackageManager packageManager = mContext.getPackageManager();
    		PackageInfo packageInfo = null;
    		try {
    			packageInfo = packageManager.getPackageInfo(mContext.getPackageName(), 0);
    		} catch (NameNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		if(packageInfo != null){
    			return packageInfo.versionName;	
    		}else{
    			return "";	
    		}
    	}
    	
    	/** SD卡是否存在 **/
    	public static File whetherExistSDcard() {
    		// 判断sd卡是否存在
    		if (Environment.getExternalStorageState().equals(
    				android.os.Environment.MEDIA_MOUNTED)) {
    			return Environment.getExternalStorageDirectory();// 获取跟目录
    		}
    		return null;
    	}
    
    	/*****
    	 * 返回指定文件夹和文件名的文件路径
    	 * 
    	 * @param FolderName
    	 * @param fileName
    	 * @return
    	 */
    	public static String getFilePath(String FolderName, String fileName) {
    		String downDirectory = null;
    		File pathSDcard = whetherExistSDcard();
    		if (pathSDcard != null) {
    			//判断文件夹是否为空
    			if (TextUtils.isEmpty(FolderName)) {
    				FolderName = "";
    			}
    			//创建文件夹
    			if(createFolder(FolderName)){
    				downDirectory = pathSDcard.toString() + File.separator + FolderName
    						+ File.separator + fileName;
    			}
    		}
    		return downDirectory;
    	}
    	
    	/****
    	 * 返回系统默认Download文件夹下的File文件路径
    	 * @param fileName   文件名称
    	 * @return
    	 */
    	public static String getDownloadFilePath(String fileName) {
    		String downDirectory = null;
    		String FolderName = "Download";
    		File pathSDcard = whetherExistSDcard();
    		if (pathSDcard != null) {
    			//创建文件夹
    			if(createFolder(FolderName)){
    				downDirectory = pathSDcard.toString() + File.separator + FolderName
    						+ File.separator + fileName;
    			}
    		}
    		return downDirectory;
    	}
    
    	/*****
    	 * 创建文件夹
    	 * @param FolderName 文件夹名称
    	 * @return
    	 */
    	public static boolean createFolder(String FolderName) {
    		
    		File pathSDcard = whetherExistSDcard();
    		if (pathSDcard != null) {
    			File file = new File(pathSDcard.toString() + File.separator + FolderName);
    			
    			if (!file.exists()) {// 目录不存在
    				file.mkdirs();
    			}
    			return true;
    		} else {
    			return false;
    		}
    	}
    
    	/****
    	 * 删除文件夹或者文件
    	 * @param file
    	 * @return
    	 */
    	public static boolean deleteDirectory(File file) {
    		if (file.isDirectory()) {
    			File[] filelist = file.listFiles();
    			for (int i = 0; i < filelist.length; i++) {
    				deleteDirectory(filelist[i]);
    			}
    			if (!file.delete()) {
    				return false;
    			}
    		} else {
    			if (!file.delete()) {
    				return false;
    			}
    		}
    		return true;
    	}
    	
    	/****
    	 * 判断是否有网络连接
    	 * @param mContext 设备上下文
    	 * @return
    	 */
        public boolean isNetworkConnected(Context mContext) {
            if (mContext != null) {
                ConnectivityManager mConnectivityManager = (ConnectivityManager) mContext
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
                if (mNetworkInfo != null) {
                    return mNetworkInfo.isAvailable();
                }
            }
            return false;
        }
    
        /****
         * 判断WiFi网络是否可用
         * @param mContext
         * @return
         */
        public boolean isWifiConnected(Context mContext) {
            if (mContext != null) {
                ConnectivityManager mConnectivityManager = (ConnectivityManager) mContext
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo mWiFiNetworkInfo = mConnectivityManager
                        .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
                if (mWiFiNetworkInfo != null) {
                    return mWiFiNetworkInfo.isAvailable();
                }
            }
            return false;
        }
        
        /****
         * 判断MOBILE网络是否可用
         * @param mContext
         * @return
         */
        public boolean isMobileConnected(Context mContext) {
            if (mContext != null) {
                ConnectivityManager mConnectivityManager = (ConnectivityManager) mContext
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo mMobileNetworkInfo = mConnectivityManager
                        .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
                if (mMobileNetworkInfo != null) {
                    return mMobileNetworkInfo.isAvailable();
                }
            }
            return false;
        }
        
        /****
         * 获取当前网络连接类型
         * @param mContext
         * @return
         * 
         */
        public static int getConnectedType(Context mContext) {
            if (mContext != null) {
                ConnectivityManager mConnectivityManager = (ConnectivityManager) mContext
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
                if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
                    return mNetworkInfo.getType();
                }
            }
            return -1;
        }
    
        /***
         * 获取手机时间按照fromat格式返回
         * @param format
         * @return
         */
    	public static String getCurrentTime(String format) {
    		Date date = new Date();
    		SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
    		String currentTime = sdf.format(date);
    		return currentTime;
    	}
    
    	/***
    	 * 获取手机时间
    	 * @return
    	 */
    	public static String getCurrentTime() {
    		return getCurrentTime("yyyy-MM-dd  HH:mm:ss");
    	}
    
    }
    

    工具类ToastUtils:
    /**
     * ToastUtils
     * @author SHI
     * 2016年3月17日 13:54:46
     */
    public class ToastUtil {
    
        private ToastUtil() {
            throw new AssertionError();
        }
    
        public static void show(Context context, int resId) {
            show(context, context.getResources().getText(resId), Toast.LENGTH_SHORT);
        }
    
        public static void show(Context context, int resId, int duration) {
            show(context, context.getResources().getText(resId), duration);
        }
    
        public static void show(Context context, CharSequence text) {
            show(context, text, Toast.LENGTH_SHORT);
        }
    
        public static void show(Context context, CharSequence text, int duration) {
            Toast.makeText(context, text, duration).show();
        }
    
        public static void show(Context context, int resId, Object... args) {
            show(context, String.format(context.getResources().getString(resId), args), Toast.LENGTH_SHORT);
        }
    
        public static void show(Context context, String format, Object... args) {
            show(context, String.format(format, args), Toast.LENGTH_SHORT);
        }
    
        public static void show(Context context, int resId, int duration, Object... args) {
            show(context, String.format(context.getResources().getString(resId), args), duration);
        }
    
        public static void show(Context context, String format, int duration, Object... args) {
            show(context, String.format(format, args), duration);
        }
    }


    到这里基本就可以实现文件下载按功能了。
    有几点需要注意:
    1:不要忘记在AndroidManifest.xml添加权限
    2:记得在AndroidManifest.xml中为UpdateAppservice添加对应的声明
    3:demo使用的xutil2.6.14.对高版本的Android兼容性可能有问题,如果出问题了,大家可以考虑使用Xutis3.0之后的或者使用别的网络框架。原理是不变的。

    最后附上demo下载:点击打开链接

    展开全文
  • 1.Android 8.0以后无法下载到SDK中 问题原因:文件的存储权限原因导致的 动态申请sdk存储权限:Android 6.0以后都是需要动态申请权限的,注意即使动态申请了权限也要在AndroidManifest.xml申请一下,因为需要兼容...

    因为Android系统版本的不同踩了不少坑,在此记录。

    1.Android 8.0以后无法下载到SDK中

    问题原因: 文件的存储权限原因导致的

    1. 动态申请sdk存储权限:Android 6.0以后都是需要动态申请权限的,注意即使动态申请了权限也要在AndroidManifest.xml申请一下,因为需要兼容低版本,低版本中没有动态申请权限一说。
    2. Android 7.0以后又对存储权限加了限制应用私有目录被限制访问 
    •  私有文件的文件权限不应再由所有者放宽,使用MODE_WORLD_READABLE/MODE_WORLD_WRITEABLE将抛出异常 
    • 向应用外传递file://URI会出发FileUriExposedException

    解决方法:

       问题一:判断版本,动态申请权限

     //----------------------------------------动态申请权限-------------------------------
     private void sdkPermission() {
            if(Build.VERSION.SDK_INT>Build.VERSION_CODES.M) {//高于6.0版本,动态申请权限
                if (ContextCompat.checkSelfPermission(context, "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(this, new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 111);
                } else {
                    downloadApk();
                }
            }
            else {
                downloadApk();//低于6.0版本,直接下载apk
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            switch (requestCode) {
                case 111:
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        //权限已经都通过了,可以下载apk到SDk中了
                        downloadApk();
                    } else {
                       // 没有申请权限
                        showPermissionDialog();
                    }
                    break;
                default:
            }
        }

       问题二:7.0以后使用FileProvider访问sdk私有文件

    FileProvider:   

         当targetSdkVersion>=24时,会存在上述问题,可能涉及到的场景有:拍照,程序安装等。 
         同时,官方在v4包(api=22开始)中引入FileProvider类用于程序间私有文件的共享。该类继承自ContentProvider,使用时需  要在清单文件中注册

    • 第一步   注册:在清单文件中通过标签注册,参考代码对属性进行说明:

      注意:当自定义类继承FileProvider时,需要更改name属性值为该类的相对路径。

    <manifest>
        ...
        <application>
            ...
            <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.mydomain.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                  android:name="android.support.FILE_PROVIDER_PATHS"
                  android:resource="@xml/file_paths" />
            </provider>
            ...
        </application>
    </manifest>

       说明:meta_data中的

                     name:为固定值android.support.FILE_PROVIDER_PATHS 

                     resource:所对应的xml文件路径

    • 第二步  resource对应的xml文件编写:作用设置可访问的共享文件 

          FileProvide只能对在paths中声明了的文件夹下的文件生成uri。

         下例子就是声明私有文件目录下images/下的文件可以临时访问(文件在res/xml/目录下),下面时一个简单的样式:

        1.创建xml:res/xml/file_paths

    2.file_paths.xml中添加代码:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <paths xmlns:android="http://schemas.android.com/apk/res/android">
           <files-path name="my_images" path="images/"/>
           <files-path name="my_docs" path="docs/"/>
      </paths>
    </resources>

    因为的子标签可以有多种,这里对所有进行说明:

    子标签中属性说明:

    • 第三步  FileProvider的使用:

    1、通过路径生成要分享的File对象。

    2、使用FileProvider生成临时访问uri (FileProvide.getUriForFile()).

    3、客户端可以使用uri通过ContentResolver.openFileDescriptor获取到一个ParcelFileDescriptor 

    案例:

    File imagePath = new File(Context.getFilesDir(), "images");
    File newFile = new File(imagePath, "default_image.jpg");
    Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
    
    //改代码生成的uri为:content://com.mydomain.fileprovider/my_images/default_image.jpg

    临时权限的授予方式 

    1. 使用Context.grantUriPermission(package,Uri,mode_flags)方法,使用想要的模式。这个方法通过mode_flags方法授予客户  端package的临时权限,有两个取值,FLAG_GRANT_URI_PERMISSION和FLAG_GRANT_WRITE_URI_PERMISSOIN。该方式允许后,可通过revokeUriPermission终止,或者手机重启后 
    2. 通过Intent 
    • 通过Intent的setData()方法将该uri放入Intent中
    • 可以为Intent设置flag,设置一个或两个, FLAG_GRANT_URI_PERMISSION和FLAG_GRANT_WRITE_URI_PERMISSOIN
    • 将Intent发送给其他app,大部分情况,通过setResult()来做 这种方法获取的权限,当接收的Activity在栈中一直活跃时都会保留,当activity栈finish时,权限会自动移除。被允许的activity所在的app的其他组件也会被允许该权限。

    案例代码:

    • 步骤一:在AndroidManifest.xml中的application注册FileProvider的清单文件
     //临时访问文件的注册
            <provider
                android:authorities="${applicationId}.android7.fileprovider"
                android:name="android.support.v4.content.FileProvider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
                ></provider>
    • 步骤二:res中创建xml包,添加file_paths.xml,在file_paths.xml中添加如下文件
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <paths>
            <external-path path="Android/data/com.example.socket.phonesafe/"        name="files_root" />
            <external-path path="." name="external_storage_root" />
        </paths>
    </resources>
    • 步骤三:代码中使用
    private void installApk(File file) {
            Uri uri=null;
            try {
                Intent intent=new Intent(Intent.ACTION_VIEW);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//为intent 设置特殊的标志,会覆盖 intent 已经设置的所有标志。
                if(Build.VERSION.SDK_INT>=24){//7.0 以上版本利用FileProvider进行访问私有文件
                    uri=FileProvider.getUriForFile(content,content.getPackageName() + ".android7.fileprovider",file);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//为intent 添加特殊的标志,不会覆盖,只会追加。
                }
                else {
                    //直接访问文件
                    uri=Uri.fromFile(file);
                    intent.setAction(Intent.ACTION_VIEW);
                }
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
                startActivity(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

     

    2.下载成功了没有跳出应用安装界面

    原因:

    Android 8.0的系统中,“未知来源应用权限”的开关被移除掉了,取而代之的是未知来源应用的管理列表,如果你想要安装某个被自己所信任的开发者的app,则需要在每一次都手动授权“安装未知应用”的许可。设置页面如下图:(在华为Android 8.0中,打开该设置页面:设置列表—>安全与隐私—>更多安全设置—>安装未知应用)

    如图所示*,若某个应用选择的是“不允许”,那么假设app手动升级的时候,就无法成功跳转到安装页面进行正常的App升级流程了,此时需要手动去授权才行,但是很多用户并不知道需要这么设置。

    解决方法:

       安装软件前,先监测是否许可了此软件的“安装未知应用”,如果没有允许就跳转到设置页面,然后用户手动允许一下,如果允许了,就可以直接安装应用了。

     

    步骤一:在AndroidManifest.xml文件中,添加REQUEST_INSTALL_PACKAGES权限

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    步骤二:判断版本号、是否允许安装此未知应用

               if(Build.VERSION.SDK_INT>Build.VERSION_CODES.O){
                        installAllowed=content.getPackageManager().canRequestPackageInstalls();//是否允许安装包
                        if(installAllowed){
                            installApk(file);//允许,安装
                        }else {
                            //跳转到设置页面,设置成允许安装
                            Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + content.getPackageName()));
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            content.startActivity(intent);
                            installApk(file);
                            return;
                        }
    
                    }
                    //版本低于8.0
                    else {
                        installApk(file);
                    }
    //安装apk
        private void installApk(File file) {
            Uri uri=null;
            try {
                Intent intent=new Intent(Intent.ACTION_VIEW);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//为intent 设置特殊的标志,会覆盖 intent 已经设置的所有标志。
                if(Build.VERSION.SDK_INT>=24){//7.0 以上版本利用FileProvider进行访问私有文件
                    uri=FileProvider.getUriForFile(content,content.getPackageName() + ".android7.fileprovider",file);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//为intent 添加特殊的标志,不会覆盖,只会追加。
                }
                else {
                    //直接访问文件
                    uri=Uri.fromFile(file);
                    intent.setAction(Intent.ACTION_VIEW);
                }
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
                startActivity(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }

    百度网盘源码:https://pan.baidu.com/s/1gKly1Syobmj1MkainAwOkw

     密码:9lj5

    注解:版本信息和要升级的apk存放在自己tomcat服务器中的webapps—ROOT中,然后开启tomcat,代码中就可以直接访问下载了。

    参考:https://blog.csdn.net/chen_white/article/details/72819814

    https://www.jianshu.com/p/e05f35fbb569

     

    注:如果你的gradle版本和我的不一样导致下载的代码不能运行,可看我另一篇代码可以解决这个问题https://blog.csdn.net/na2609613672/article/details/89086952

    展开全文
  • 这样就完成了更新的目的,**注意:**这里不是热更新方案,热更新指的是在程序内部将资源、逻辑替换 二、分析需求 做过Unity的人应该对Window的包不陌生通常是三个文件如下图(部分可能会多,不过无所谓) 把Window...
  • Android实现APP在线下载更新,实现了软件自动更新功能的方法.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • 只需单击按钮,即可帮助您完全禁用或启用Windows系统上的自动更新。 此实用程序是便携式的,这意味着您不再需要经过安装过程, 并且在移除硬盘后,将不会有任何垃圾留在硬盘上。 下载地址:...
  • 智能手机容量越来越大,用户手机里下载的App越来越多,自动更新的弊端也...”北京市民林晨告诉笔者,自己手机里下载了70余款软件,涵盖学习、摄影、视频、游戏等不同类别,尽管手机内存充足,但仍不愿意开启自动更新...
  • 想要实现一个android应用,自动更新下载APK软件的方法,我采取的是以下几步方法: 1.每次进入主界面时,获取服务器的数据,看是否是最新版本,是,则无操作,否,则进行以下步骤; 2.弹出是否更新软件的对话框,点击...
  • Qt 实现软件自动更新

    千次阅读 2020-06-05 15:43:10
    一、自动更新程序流程 加载本地配置文件获取获取保存的版本号 每次启动程序,首先从服务器请求最新的版本信息文件(包括版本号,压缩包下载地址,更新时间,更新说明) 解压下载的文件获取服务器版本号,与本地版本...
  • Delphi 软件自动更新模块源码示例,也就是实现软件的自动升级功能,自动连接服务器查找最新版本,然后下载软件,安装。下载时候显示软件大小,连接速度,下载百分比,进度条显示。
  • 1 前言  长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/...然而当一个应用 必须要使用C/S结构才能很好的实现其功能的时候,我们该如何解决客户端的部署与自动升级问题?部署很简单,只要点击...
  • 第二步:新建一个UpdateManager.java类,负责软件更新功能模块,代码如下: [java] view plaincopy package com.tutor.update; import java.io.File; import java.io.FileOutpu
  • Delphi软件自动更新程序,自动升级程序为单独程序,由主程序调用,以下为调用说明:  AutoUpgrader.exe ScriptURL CurVersion SoftName WinHandle ExitMsgID ProcessID  参数说明:  ScriptURL - 升级脚本文件...
  • link环境下使用codefirst制作的《网盘软件》,下载器如何自动更新
  • android开发进行自动更新时怎么下载软件到手机内存,显示实现下载到SD卡了 // 判断SD卡是否存在,并且是否具有读写权限 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { ...
  • C# 软件自动更新升级

    千次阅读 2014-02-18 14:57:28
    C# 软件自动更新升级 原理 服务器端的结构是这样的: 其工作原理如下: Update.asmx仅提供一个功能,就是检测是否需要更新,在需要更新的时候就返回一个更新地址,通常情况下返回的地址就是...
  • 用VC++实现的软件自动更新模块 Updater.exe源码。主程序从服务器下载配置文件后对比本地配置文件,有新版本则打开Updater.exe进行自动更新,可以显示需要下载的文件列表,文件大小,文件下载状态等。CSDN我找了,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,276
精华内容 1,310
关键字:

下载自动更新软件