- 寸头二姐
-
随着大数据集群的使用,大数据的安全受到越来越多的关注一个安全的大数据集群的使用,运维必普通的集群更为复杂。
集群的安全通常基于kerberos集群完成安全认证。kerberos基本原理可参考 :一张图了解Kerberos访问流程
Spark应用(On Yarn模式下)在安全的hadoop集群下的访问,需要访问各种各样的组件/进程,如ResourceManager,NodeManager,NameNode,DataNode,Kafka,Hmaster,HregionServer,MetaStore等等。尤其是在长时运行的应用,如sparkStreaming,StructedStreaming,如何保证用户认证后的长期有效性,其安全/认证更为复杂。
一个Spark应用提交用户要先在kdc中完成用户的认证,及拿到对应service服务的票据之后才能访问对应的服务。由于Spark应用运行时涉及yarnclient,driver,applicationMaster,executor等多个服务,这其中每个进程都应当是同一个用户启动并运行,这就涉及到多个进程中使用同一个用户的票据来对各种服务进行访问,本文基于Spark2.3对此做简要分析。
spark应用的提交用户认证之后才能提交应用,所以在yarnclient/driver的逻辑中必然会执行到kerberos认证相关的登录认证。然而其他的进程如applicationMaster,executor等均需要经过认证,应用提交后才由用户启动,这些进程则可以不进行kerberos认证而是利用Hadoop的token机制完成认证,减小kerberos服务压力,同时提高访问效率。
Hadoop的token实现基类为org.apache.hadoop.security.token.Token,
不同的服务也可hadoop的token来交互,只要使用不同的identifer来区分token即可。 如NMTokenIdentifier, AMRMTokenIdentifier,AuthenticationTokenIdentifier等不同的tokenIdentifier来区分不同的服务类型的token。
此处yarnclient指的是向ResourceManager提交yarn应用的客户端。在spark中,向yarn提交应用有两种应用有yarn-client,yarn-cluster模式。在这两种应用模式下提交应用,yarn client逻辑有些许不同。
安全hadoop场景下spark的用户登录认证机制
在client的submitApplication方法中提交app,之后创建amContext,准备本地资源,此时会将本地的文件上传至HDFS,其中就包括keytab文件,同时会生成 spark_conf .properties配置文件以供am使用,该配置文件中会包含keytab的配置
其中的amKeytabFileName是在setUpCredentials时设置如下,该值为指定的keytab文件加上随机的字符串后缀,骑在am重点使用,可参考下节的介绍。
获取相关组件的token,注意:此处的token均非与yarn服务交互相关token,这里只有与HDFS,HBASE,Hive服务交互的token。
}
Spark中常访问的服务使用token机制的有hive,hbase,hdfs,对应的tokenProvider如下:
以HbaseDelegationTokenProvider为例,主要是通过反射调用hbase的TokenUtil类的obtainTOken方法,对应的obtainDelegationTokens方法如下:
PS : HBase的token获取的用户需要具有hbase:meta表的exec权限,否则无法成功获取token
在获取token后,将token设置到amContainer中,并放入appContext中
在yarn-client模式下,driver在yarnclient进程中启动,同样需要访问业务层及集群的相关组件如hdfs。driver通过读取am更新在hdfs路径下的credentials文件来保证driver节点的token有效。
在yarn-cluster模式下,driver运行在applicationMaster的JVM中,其安全相关由Am同一操作
applicationMaster是Yarn进行应用调度/管理的核心,需要与RM/NM等进行交互以便应用运行。其中相关的交互均通过token完成认证,认证实现由Yarn内部框架完成。查看am日志发现,即是在非安全(非kerberos)的场景下,同样会使用到token。而与hdfs,hbase等服务交互使用的token则需Spark框架来实现。
在ResourceManager接收到应用提交的ApplicationSubmissionContext后,在其AmLauncher.java的run方法中为am设置生成“YARN_AM_RM_TOKEN,该token用于am于rm通信使用”
Am在启动之后,会向ResourceManager申请container,并与对应的NodeManager通信以启动container。然而AM与NM通信的token是如何得到的呢?
查看AMRMClientImpl类可以看到,AM向RM发送分配请求,RM接收到请求后,将container要分配至的NM节点的Token放置response中返回给AM。Am接收到response后,会保存NMToken,并判定是否需要更新YARN_AM_RM_TOKEN
RM通过ApplicationMasterService响应allocation请求
AM在准备启动container时,将当前用户的token都设置进ContainerLaunchContext中
查看Am启动命令大致如下,可以发现有指定配置文件,而该配置文件即为yarnclient生成上传至hdfs,在am启动前由NodeManager从hdfs中copy至本地路径,供container使用:
查看此配置文件可以看到有如下配置项:
下图为am进程使用到的资源文件
如上可以看出,am虽然运行在集群中,但运行时认证相关的资源已经准备就绪。下面分析其运行中关于安全的逻辑
在applicationMaster中,定期更新token,并写入文件到hdfs的相关目录,并清理旧文件以供各executor使用。
在ApplicationMaster启动后,进行login登录并启动名为am-kerberos-renewer的dameon线程定期登录,保证用户认证的有效性
private val ugi = {
val original = UserGroupInformation.getCurrentUser()
在am中启动AMCredentialRenewerStarter线程,调度认证登录及token renew逻辑
在scheduleLoginFromKeytab中,会周期调度登录,token获取更新写入hdfs文件等操作。
其核心逻辑如下
调度周期:
调度流程:
executor的认证同样使用的是token机制。executor启动之后,根据driver启动设置的${spark.yarn.credentials.file}启动token更新:
Executor中的token更新是读取hdfs目录 {timeStamp}-${nextSuffix}目录下的文件,读取到缓存中,以便保证读取到的是更新后的token使用。
Spark框架完成的kerberos认证及使用token与其他服务交互的机制使用较为简单,只需要在提交应用时的spark-submit命令行中加入--principal appuserName --keytab /path/to/user.keytab即可
相关推荐
mtoken钱包里的url地址不正确怎么办啊
mtoken钱包里的url地址不正确是因为你输入的链接网址(url)有错误,不能被其识别。可以重新检查一下url链接。1、查看地址中有无“。”或者“空格”“中文”“大小写”等。2、格式是否完整,完整的url地址应该像网址一样包括主机名和文件名,如果明显跟网址不一样那就错了。mtoken系列身份认证锁(是北京世纪龙脉科技有限公司开发的四大产品系列之一。2023-08-10 06:12:011
mtokengm3000替换失败
网络的问题。mtokengm3000替换失败多数是网络连接异常导致。1、首先打开电脑检查网络。2、其次打开进行测试网络连接是否异常。3、最后点击重新进入即可。2023-08-10 06:12:081
imtoken更改权限失败
您要问的是mtoken更改权限失败的原因吗?机设置或是安全软件进行了设置、系统平台问题。1、机设置或是安全软件进行了设置,用户需要前往修改,开放权限。2、系统平台问题,有可能系统平台出现了问题,用户可以先退出系统,稍等片刻再进行尝试。2023-08-10 06:12:141
手机里Mtoken是啥
QQ手机令牌2023-08-10 06:12:221
gm3000中间件是什么软件可以删除吗
不可以中间件是应用程序调用Key的接口,中间件安装完成后,在系统目录WindowsSystem32下会存放相关产品名称的DLL,所以建议用户不要卸载删除,避免信息丢失。以GM3000为例:查看目录下是否存在mtoken_gm3000.dll,若没有请重新安装中间件。消息中间件不能及时更新投递状态,在投递过程中就会产生的消息重复接收。中间件在消息发送中的问题消息发送端应用的消息重复发送:1、消息发送端发送消息给消息中间件,消息中间件收到消息并成功存储,而这时消息中间件出现了问题,导致应用端没有收到消息发送成功的返回因而进行重试产生了重复。2、消息中间件因为负载高响应变慢,成功把消息存储到消息存储中后,返回“成功”这个结果时超时。3、消息中间件将消息成功写入消息存储,在返回结果时网络出现问题,导致应用发送端重试,而重试时网络恢复,由此导致重复。2023-08-10 06:12:293
现在国内做得好区块链钱包有哪些?
之前都是用imtoken,因为出的比较早,cobo和bitkeep还有ETbank都有用过,不过感觉ETbank的利息高点。2023-08-10 06:13:334
阅读Android的源代码时发现许多符号都是以m开头的,如mToken,mWindow之类的 这个m代表什么意思?
member,类成员变量的意思,不仅仅是android,很多语言都是这样的。方便大家读代码。一看的m开头的就知道这个是成员变量。2023-08-10 06:13:552
有人知道overridePendingTransition页面跳转动画的原理么
1.Activity中overridePendingTransition,显然我们都用这个的啦,看代码:ActivityManagerNative.getDefault().overridePendingTransition( mToken, getPackageName(), enterAnim, exitAnim); 目标转向ActivityManagerNative2.ActivityManagerNative是神马东东?看其定义:public abstract class ActivityManagerNative extends Binder implements IActivityManager 这可以知道,他是xxxxxx,我日,这才发现需要Android系统的IPC只是。 好吧,其实是这样,android本身有很多Service,这些服务从开机启动就一直在跑,比如media,比如windowmanager,这些服务对外提供接口,有些是一直到最上层都要用到的,比如Media,有些只给内部用,比如windowmanager(亲,我说的是这个service,别跟我们用的WindowManager混淆了),只给内部用和给上层用是两种不同的概念。为毛?因为内部用的话他们是同一个进程,没必要跨进程通信,也就是没ipc问题,而给外部用,就需要Ipc了。 扯远了,说说我们这个ActivityManagerNative,他就是IActivityManager的【本地】代理,ActivityManagerNative.getDefault()得到的就是IActivityManager对象。IActivityManager又是毛???没错,它是WindowManagerService的顾客。。。它里面就是跟WindowManagerService通信的啦。。。(android binder ipc神马的最讨厌了)3.呃,回到1中说的那个ActivityManagerNative.getDefault(),上面说他是得到IActivityManager用的,IActivityManager里面的overridePendingTransition直接跟server端通话。 “Hello,啊 ,WindowManagerService,我是你的代理IActivityManager君啊,刚接到任务要改变activity的切换画面啊。" "ok,IActivityManager,在外面风吹日晒的辛苦你了,其他的交给我吧。作为NB哄哄的Service大人,我帮你解决之。“ 毫不犹豫的,WindowManagerService执行以下代码:public void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim) { if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { mNextAppTransitionPackage = packageName; mNextAppTransitionEnter = enterAnim; mNextAppTransitionExit = exitAnim; } }4. 额,这下已经到了WindowManagerService了,这个方法(overridePendingAppTransition)中mNextAppTransitionEnter等变量赋值。这些变量在window进行切换的时候会进行处理。remove->removeWindow->removeWindowLocked->applyAnimationLocked(注意,这些说的都是WindowManagerService中的方法)那么这个remove(具体是 public void remove(IWindow window) { removeWindow(this, window); })什么时候用的呢,这个,这个。。。。在ViewRoot和SurfaceView中都会调用到的。2023-08-10 06:14:031
银联在线和支付宝,android应用怎么调用
一、 支付宝平台的集成 在技术集成之前,商户需要在https://ms.alipay.com进行注册,并签约安全支付服务。签约成功后可获取支付宝分配的合作商户ID(PartnerID),账户ID(SellerID),调用接口时使用。 支付细节的实现,主要通过支付宝提供的一个支付安全服务安装包alipay_plugin_20120428msp.apk,首次使用,首先检查是否安装此插件,没有会提示安装。具体的支付细节,在这个插件内完成。大部分的支付平台也都是采用的这种方式。 调用支付宝的接口进行支付,主要有以下几个步骤 1. 将商户ID,收款帐号,外部订单号,商品名称,商品介绍,价格,通知地址封装成订单信息 2. 对订单信息进行签名 3. 将订单信息,签名,签名方式封装成请求参数 4. 调用pay方法。 主要流程图如下: 支付接口pay方法的调用如下: 。。。 // start pay for this order. // 根据订单信息开始进行支付 try { // prepare the order info. // 准备订单信息 String orderInfo = getOrderInfo(position); // 这里根据签名方式对订单信息进行签名 String signType = getSignType(); String strsign = sign(signType, orderInfo); Log.v("sign:", strsign); // 对签名进行编码 strsign = URLEncoder.encode(strsign); // 组装好参数 String info = orderInfo + "&sign=" + """ + strsign + """ + "&" + getSignType(); Log.v("orderInfo:", info); // start the pay. // 调用pay方法进行支付 MobileSecurePayer msp = new MobileSecurePayer(); boolean bRet = msp.pay(info, mHandler, AlixId.RQF_PAY,this); if (bRet) { // show the progress bar to indicate that we have started // paying. // 显示“正在支付”进度条 closeProgress(); mProgress = BaseHelper.showProgress(this,null, "正在支付",false, true); } else ; } catch (Exception ex) { Toast.makeText(AlixDemo.this, R.string.remote_call_failed, Toast.LENGTH_SHORT).show(); } 。。。 /** * 向支付宝发送支付请求 * * @param strOrderInfo * 订单信息 * @param callback * 回调handler * @param myWhat * 回调信息 * @param activity * 目标activity * @return */ public boolean pay(final String strOrderInfo,final Handler callback, final int myWhat, final Activity activity) { if (mbPaying) return false; mbPaying = true; // mActivity = activity; // bind the service. // 绑定服务 if (mAlixPay ==null) { // 绑定安全支付服务需要获取上下文环境, // 如果绑定不成功使用mActivity.getApplicationContext().bindService // 解绑时同理 mActivity.getApplicationContext().bindService( new Intent(IAlixPay.class.getName()),mAlixPayConnection, Context.BIND_AUTO_CREATE); } // else ok. // 实例一个线程来进行支付 new Thread(new Runnable() { public void run() { try { // wait for the service bind operation to completely // finished. // Note: this is important,otherwise the next mAlixPay.Pay() // will fail. // 等待安全支付服务绑定操作结束 // 注意:这里很重要,否则mAlixPay.Pay()方法会失败 synchronized (lock) { if (mAlixPay ==null) lock.wait(); } // register a Callback for the service. // 为安全支付服务注册一个回调 mAlixPay.registerCallback(mCallback); // call the MobileSecurePay service. // 调用安全支付服务的pay方法 String strRet =mAlixPay.Pay(strOrderInfo); BaseHelper.log(TAG,"After Pay: " + strRet); // set the flag to indicate that we have finished. // unregister the Callback, and unbind the service. // 将mbPaying置为false,表示支付结束 // 移除回调的注册,解绑安全支付服务 mbPaying = false; mAlixPay.unregisterCallback(mCallback); mActivity.getApplicationContext().unbindService( mAlixPayConnection); // send the result back to caller. // 发送交易结果 Message msg = new Message(); msg.what = myWhat; msg.obj = strRet; callback.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); // send the result back to caller. // 发送交易结果 Message msg = new Message(); msg.what = myWhat; msg.obj = e.toString(); callback.sendMessage(msg); } } }).start(); return true; } 调用了支付服务之后,有两种方式返回交易结果: 1. 支付结果作为接口返回的字符串返回。返回的参数包含在result字符串中,具体再进行解析。 2. 支付宝服务器通知。商户需要提供一个http协议的接口,包含在参数里传递给安全支付,即notify_url。支付宝服务器在支付完成后,会用POST方法调用notufy_url,以xml为数据格式传输支付结果。需要注意的是,商户服务器收到支付宝发的通知之后,需要返回一个纯字符串“success”,不然支付宝的服务器会持续调用七次回调url提供的接口。 集成需要的交易费用方面0-1万元内是2.5%的费率,1-10万是2.4%,10-100万是2.2%,100万以上2.0%。 PS :亲测 AliPayInfo aliPayInfo=new AliPayInfo(); AliPay aliPay=new AliPay((Activity)OtherPayDlg.this.mContext, mHandler); aliPay.pay(aliPayInfo.toString()); OtherPayDlg.this.dismiss(); 出现问题一:按照说明文档导入alipay.jar 出现AliPay 找不到,然后项目根目录下新建一个 libs文件夹,把要加的包放到这个目录下,右键 Build Path -> Use as source folder 成功可以引用,但是没有弹出界面 二、 财付通平台的集成 财付通的集成和支付宝的非常相似(腾讯的传统?→_→)。财付通也是提供了一个财付通安全支付服务应用TenpayService.apk用于处理交易的细节。对于此支付应用,财付通和支付宝的使用方式是一样的。一种是捆绑预置,即打包在assets目录下,另一种是放到自己的服务器中,通过检查更新的方式动态加载。实际集成中可采用二者结合方式,初次使用使用预置apk,之后检查更新动态下载。 但是调用支付接口之前,增加了一个获取tokenid的过程,tokenid用于同财付通service进行交互。过程如下: 1. 用户在商户APP 选择商品,使用财付通支付 2. 商户APP向商户server 请求使用财付通支付 3. 商户server按照“支付初始化接口”的要求组织数据请求财付通“支付初始化接口”,接收初始化成功后返回的tokenid 4. 商户server将生成的tokenid 返回给商户APP 5. 商户APP使用tokenid 调用财付通支付service 6. 财付通支付service 在验证tokenid 后向用户展示支付中心,显示订单信息及相关用户信息 7. 用户在支付中心输入支付密码执行支付 8. 财付通支付service 向财付通后台server 请求执行支付,并实时接收支付结果 9. 支付成功后财付通支付service 向用户展示支付成功UI,在用户点击“返回商户网站”后回调商户App 10. 财付通后台server 在支付成功后会通过“支付成功通知接口”在后台通知商户server 支付状态。 接收支付接口返回结果方面,财付通对于方法返回值,不是直接返回的,而是通过handler回调,handler和msgId作为一个参数传入接口,支付接口pay()方法的返回值只是个true false,用于区分调用成功或者失败。其实跟淘宝的方式大同小异。对于notify_url,是财付通是通过get方式调用回调url,只返回支付成功的订单。同样的,商户服务器在接收到财付通的调用之后,需要返回纯字符串“success”“fail”表示处理成功或失败。 调用支付接口的代码如下: //构造支付参数 HashMap<String, String> payInfo = new HashMap<String, String>(); payInfo.put("token_id",mTokenId); //财付通订单号token_id payInfo.put("bargainor_id","1234567890"); //财付通合作商户ID,此为演示示例 // payInfo.put("order_type", "1"); payInfo.put("caller","com.tenpay.android.appDemo"); //去支付 tenpayHelper.pay(payInfo,mHandler, MSG_PAY_RESULT); 财付通的服务费率是1%,另外有相关的套餐可以优惠。 三、 易宝支付平台集成 与支付宝和财付通不同的是,易宝集成时,并没有提供一个支付应用apk,只有一个jar包。是一个library project。因为在集成时,需要在manifest文件里面声明支付页面的activity。同时在调用支付页面时,需要用startActivityForResult方式进入,支付结果会通过onActivityResult方法返回。易宝同样支持服务端回调,但比较纠结的是,易宝的服务端回调url,不能在代码中传入,需要在易宝的网站进行配置。只有支付成功时才会触发此回调,以get方式调用。 调用支付接口的代码如下:其中customerNumber参数是签约之后才能获取到的。requestId为调用方自定义的订单流水号。 private void startPay(String customerNumber, String chennal) { String amount = etAmount.getText().toString(); String productName = etProductName.getText().toString(); String productDesc = etProductDesc.getText().toString(); if(TextUtils.isEmpty(productName) || TextUtils.isEmpty(amount)) { Toast.makeText(YeepayExampleActivity.this,"", Toast.LENGTH_SHORT); } Intent intent = new Intent(getBaseContext(), YeepayPlugin.class); intent.putExtra("customerNumber", customerNumber); Random random = new Random(); String time = "" + System.currentTimeMillis(); String requestId = time + random.nextInt() % 10000; intent.putExtra("requestId", requestId); intent.putExtra("amount", amount); intent.putExtra("productName", productName); intent.putExtra("time", time); intent.putExtra("productDesc", (productDesc ==null) ? "" : productDesc); intent.putExtra("support", chennal); intent.putExtra("environment","ENV_TEST" ); StringBuilder builder = new StringBuilder(); builder.append(CUSTOMER_NUMBER).append("$"); builder.append(requestId).append("$"); builder.append(amount).append("$"); builder.append(productName).append("$"); builder.append(time); String hmac = YeepayUtils.hmacSign(builder.toString(),KEY); Log.e("YeepayExampleActivity","hmac" + hmac); intent.putExtra("hmac", hmac); startActivityForResult(intent, 200); } 易宝集成后的费率需要和易宝的客户经理面谈决定 四、 银联在线支付集成 银联的支付应用同支付宝和财付通相同,采用的是独立apk的方式提供服务。调用支付接口采用的startActivity的方式,相关参数通过bundle传递,调用示例如下: bundle.putBoolean(USE_TEST_MODE,true); bundle.putString(SP_ID,"0009"); bundle.putString(SECURITY_CHIP_TYPE,null); bundle.putString(SYS_PROVIDE,"00000001"); bundle.putString(PAY_DATA, payData); … Intent startIntent = new Intent(); // startIntent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); startIntent.putExtras(bundle); startIntent.setClassName(UPPayUtils.PACKAGE_NAME, UPPayUtils.ACTIVITY_NAME); // activity.startActivityForResult(startIntent, UPPayUtils.STARTE_UPPAY); activity.startActivity(startIntent); 与以上三种支付平台不同的是,银联支付接口的返回值是通过广播的形式发送的。不支持商户服务端的回调url。2023-08-10 06:14:311
vb绘制图像
这种绘图问题来找我嘛……(分好寒酸。。)传说中的GDI+隆重出场!……GDI+是最快的。可以超过VB任何绘图语句1.建立一个模块,复制下面代码:Option ExplicitPublic Type GdiplusStartupInput GdiplusVersion As Long DebugEventCallback As Long SuppressBackgroundThread As Long SuppressExternalCodecs As LongEnd TypePublic Enum GpStatus Ok = 0 GenericError = 1 InvalidParameter = 2 OutOfMemory = 3 ObjectBusy = 4 InsufficientBuffer = 5 NotImplemented = 6 Win32Error = 7 WrongState = 8 Aborted = 9 FileNotFound = 10 ValueOverflow = 11 AccessDenied = 12 UnknownImageFormat = 13 FontFamilyNotFound = 14 FontStyleNotFound = 15 NotTrueTypeFont = 16 UnsupportedGdiplusVersion = 17 GdiplusNotInitialized = 18 PropertyNotFound = 19 PropertyNotSupported = 20End EnumPublic Enum LinearGradientMode LinearGradientModeHorizontal " 0 LinearGradientModeVertical " 1 LinearGradientModeForwardDiagonal " 2 LinearGradientModeBackwardDiagonal " 3End EnumPublic Enum WrapMode WrapModeTile " 0 WrapModeTileFlipX " 1 WrapModeTileFlipY " 2 WrapModeTileFlipXY " 3 WrapModeClamp " 4End EnumPublic Type POINTL x As Long y As LongEnd TypePublic Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As GpStatusPublic Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As GpStatusPublic Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, graphics As Long) As GpStatusPublic Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As GpStatusPublic Declare Function GdipGraphicsClear Lib "gdiplus" (ByVal graphics As Long, ByVal lColor As Long) As GpStatusPublic Declare Function GdipCreateLineBrushI Lib "gdiplus" (Point1 As POINTL, Point2 As POINTL, ByVal color1 As Long, ByVal color2 As Long, ByVal WrapMd As WrapMode, lineGradient As Long) As GpStatusPublic Declare Function GdipFillRectangleI Lib "gdiplus" (ByVal graphics As Long, ByVal Brush As Long, ByVal x As Long, ByVal y As Long, ByVal Width As Long, ByVal Height As Long) As GpStatusPublic Declare Function GdipDeleteBrush Lib "gdiplus" (ByVal Brush As Long) As GpStatusDim mToken As LongPublic Sub InitGDIPlus() Dim uInput As GdiplusStartupInput uInput.GdiplusVersion = 1 If GdiplusStartup(mToken, uInput) <> Ok Then MsgBox "GDI+ 初始化错误。程序即将关闭。", vbCritical, "InitError" End End IfEnd SubPublic Sub TerminateGDIPlus() GdiplusShutdown mTokenEnd Sub2.窗体上复制下面代码:Option ExplicitDim g As Long, Brush As LongDim p1 As POINTL, p2 As POINTLPrivate Sub Form_Load() Picture1.ScaleMode = 2 Picture1.AutoRedraw = True Me.ScaleMode = 2 p1.x = Picture1.Left p1.y = Picture1.Top p2.x = p1.x + Picture1.Width p2.y = p1.y + Picture1.Height Call InitGDIPlus GdipCreateFromHDC Picture1.hDC, g GdipCreateLineBrushI p1, p2, &HFFFF00FF, &HFF00FF00, WrapModeTileFlipY, Brush GdipFillRectangleI g, Brush, p1.x, p1.y, p2.x - p1.x, p2.y - p1.yEnd SubPrivate Sub Form_Unload(Cancel As Integer) GdipDeleteBrush Brush GdipDeleteGraphics g TerminateGDIPlusEnd Sub注意这一行 GdipCreateLineBrushI p1, p2, &HFFFF00FF, &HFF00FF00, WrapModeTileFlipY, Brush&HFFFF00FF, &HFF00FF00分别是两个颜色,对应AlphaRedGreenBlue即&HFFFF00FF代表Alpha=255,Red=255,Green=0,Blue=2552023-08-10 06:14:425
android调用finish后为什么没有立即执行onDestroy方法
作者:Long Chen链接:http://www.zhihu.com/question/31116186/answer/50842598来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。在你的activity动作完成的时候,或者Activity需要关闭的时候,调用此方法。当你调用此方法的时候,系统只是将最上面的Activity移出了栈,并没有及时的调用onDestory()方法,其占用的资源也没有被及时释放。因为移出了栈,所以当你点击手机上面的“back”按键的时候,也不会找到这个Activity。但是系统调用ondestory时,activity就是真正的销毁了。因此android程序员只能精确的控制activity的创建时间,并不能确定activity的销毁时间。activity的finish()会调用到这一步private void finish(boolean finishTask) { if (mParent == null) { int resultCode; Intent resultData; synchronized (this) { resultCode = mResultCode; resultData = mResultData; } if (false) Log.v(TAG, "Finishing self: token=" + mToken); try { if (resultData != null) { resultData.prepareToLeaveProcess(); } if (ActivityManagerNative.getDefault() .finishActivity(mToken, resultCode, resultData, finishTask)) { mFinished = true; } } catch (RemoteException e) { // Empty } } else { mParent.finishFromChild(this); }}然后通知通信组件intent去调用prepareToLeaveProcess()等等finishactivity()public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask)throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeInt(resultCode); if (resultData != null) { data.writeInt(1); resultData.writeToParcel(data, 0); } else { data.writeInt(0); } data.writeInt(finishTask ? 1 : 0); mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); boolean res = reply.readInt() != 0; data.recycle(); reply.recycle(); return res;}2023-08-10 06:14:574
android acitivy和window的区别
我想大多数人,对于这3个东西的概念能区分,但是具体区别在哪却很难说出来。我这里根据我个人的理解来讲讲我个人对这3个概念的理解。当然这里设计到通用的事件窗口模型等通用GUI设计,我这里就不打算讲了,纯粹从概念上来进行区分。Activity是Android应用程序的载体,允许用户在其上创建一个用户界面,并提供用户处理事件的API,如onKeyEvent, onTouchEvent等。 并维护应用程序的生命周期(由于android应用程序的运行环境和其他操作系统不同,android的应用程序是运行在框架之内,所以他的应用程序不能当当从进程的级别去考虑,而更多是从概念上去考虑。android应用程序是由多个活动堆积而成,而各个活动又有其独立的生命周期)。Activity本身是个庞大的载体,可以理解成是应用程序的载体,如果木有Activity,android应用将无法运行。也可以理解成android应用程序的入口。Acivity的实例对象由系统维护。系统服务ActivityManager负责维护Activity的实例对象,并根据运行状态维护其状态信息。但在用户级别,程序员可能根愿意理解成为一个界面的载体。但仅仅是个载体,它本身并不负责任何绘制。Activity的内部实现,实际上是聚了一个Window对象。Window是一个抽象类,它的具体是在android_src_home/framework/policies/base/phone/com/android/internal/policy/impl目录下的PhoneWindow.java。当我们调用Acitivity的 setContentView方法的时候实际上是调用的Window对象的setContentView方法,所以我们可以看出Activity中关于界面的绘制实际上全是交给Window对象来做的。绘制类图的话,可以看出Activity聚合了一个Window对象。下面是PhoneWindow中的setContentView方法的实现: @Override public void setContentView(View view, ViewGroup.LayoutParams params) { if (mContentParent == null) { installDecor(); } else { mContentParent.removeAllViews(); } mContentParent.addView(view, params); final Callback cb = getCallback(); if (cb != null) { cb.onContentChanged(); } }Window内部首先判断mContentParent是否为空,然后调用installDecor方法(安装装饰器),我们看看这个方法如何实现的 private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); mDecor.setIsRootNamespace(true); } if (mContentParent == null) { mContentParent = generateLayout(mDecor); mTitleView = (TextView)findViewById(com.android.internal.R.id.title); if (mTitleView != null) { if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) { View titleContainer = findViewById(com.android.internal.R.id.title_container); if (titleContainer != null) { titleContainer.setVisibility(View.GONE); } else { mTitleView.setVisibility(View.GONE); } if (mContentParent instanceof FrameLayout) { ((FrameLayout)mContentParent).setForeground(null); } } else { mTitleView.setText(mTitle); } } } }在该方法中,首先创建一个DecorView,DecorView是一个扩张FrameLayout的类,是所有窗口的根View。我们在Activity中调用的setConctentView就是放到DecorView中了。这是我们类图的聚合关系如下:Activity--->Window--->DecorView这是我们得出这3个类之间最直接的一个关系。我们详细分析一下,类对象是如何被创建的。先不考虑Activity的创建(因为 Acitivity的实例由ActivityManager维护,是在另一个进程设计到IPC的通信,后面会讲到),而考虑Window和View的创建。Activity被创建后,系统会调用它的attach方法来将Activity添加到ActivityThread当中。我们找到Activity的attach方法如下:final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance, HashMap<String,Object> lastNonConfigurationChildInstances, Configuration config) { attachBaseContext(context); mWindow= PolicyManager.makeNewWindow(this); mWindow.setCallback(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } mUiThread = Thread.currentThread(); mMainThread = aThread; mInstrumentation = instr; mToken = token; mIdent = ident; mApplication = application; mIntent = intent; mComponent = intent.getComponent(); mActivityInfo = info; mTitle = title; mParent = parent; mEmbeddedID = id; mLastNonConfigurationInstance = lastNonConfigurationInstance; mLastNonConfigurationChildInstances = lastNonConfigurationChildInstances; mWindow.setWindowManager(null, mToken, mComponent.flattenToString()); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config; }我们看红色的代码部分,就是创建Window对象的代码。感兴趣的同学可以跟踪去看看具体是如何创建的。其实很简单,其内部实现调用了Policy对象的makeNewWindow方法,其方法直接new了一个PhoneWindow对象如下:public PhoneWindow makeNewWindow(Context context) { return new PhoneWindow(context); }这时我们已经可以把流程串起来,Activity创建后系统会调用其attach方法,将其添加到ActivityThread当中,在attach方法中创建了一个window对象。下面分析View的创建。我们知道Window聚合了DocerView,当用户调用setContentView的时候会把一颗View树仍给DocerView.View树是已经创建好的实例对象了,所以我们研究的是DocerView是个什么东西,它是如何被创建的。我们回头看看Window实现里边的setContentView方法,我们看上面代码的红色部分setContentView-> installDecor-> generateDecor.generateDecor直接new了一个DecorView对象: protected DecorView generateDecor() { return new DecorView(getContext(), -1); }我们可以去看看DecorView的实现,它是PhoneWindow的一个内部类。实现很简单,它默认会包含一个灰色的标题栏,然后在标题栏下边会包含一个空白区域用来当用户调用setContentView的时候放置用户View,并传递事件,这里不做详细分析,感兴趣同学可以自己研究研究。当DecorView创建好之后再回到Window中的setContentView方法中来,见上面代码蓝色部分,调用 mContentParent.addView(view, params);来将用户的View树添加到DecorView中。到这时为止,我想我们已经很清晰的认识到它们3者之间的关系,并知道其创建流程。现在总结一下:Activity在onCreate之前调用attach方法,在attach方法中会创建window对象。window对象创建时并木有创建Decor对象对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的View 添加到DecorView中。2023-08-10 06:15:191
weblogic 中部署struts写的项目,运行报struts标签错误,请教高手
标签包是否导入 ,或是否正确使用~2023-08-10 06:15:411
谷歌浏览器提示“此网站使用的插件(application/x-mtokenplugin)不受支持”应该怎么破,求指教
通过信任网站使用插件能解决该问题,步骤如下:1、直接在谷歌浏览器那里打开设置菜单,找到图示项并选择跳转。2、下一步,需要按照安全→受信任的站点→站点的顺序进行点击。3、如果没问题,就继续确定添加相关对象。4、这样一来等发现此网站已经恢复正常以后,即可实现要求了。2023-08-10 06:15:481
谷歌浏览器提示“此网站使用的插件(application/x-mtokenplugin)不受支持”应该怎么破,求指教
通过信任网站使用插件能解决该问题,步骤如下:1、直接在谷歌浏览器那里打开设置菜单,找到图示项并选择跳转。2、下一步,需要按照安全→受信任的站点→站点的顺序进行点击。3、如果没问题,就继续确定添加相关对象。4、这样一来等发现此网站已经恢复正常以后,即可实现要求了。2023-08-10 06:16:251
如何使新浪微博支持SSO授权
添加URL scheme,在你的工程设置项,targets 一栏下,选中自己的 target,在 Info->URL Types 中添加 URL Schemes,此值是 sso 登录时回调时所用。如果使用的是Xcode3或更低版本,则需要在plist文件中添加。如果你使用我们默认的新浪微博账号的话,将url scheme修改为“sinaweibosso.126663232”,否则是“sinaweibosso.你的新浪微博appkey”在你的`AppDelegate`文件里面`#import "UMSocialSnsService.h"`并实现下面的方法: - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { // 如果你除了使用我们sdk之外还要处理另外的url,你可以把`handleOpenURL:wxApiDelegate:`的实现复制到你的代码里面,再添加你要处理的url。return [UMSocialSnsService handleOpenURL:url wxApiDelegate:nil]; }2023-08-10 06:17:111
win32程序创建线程用c语言库的_beginthread还是API的CreateThread?哪种用的多?
让我们简单回顾一下历史。很早以前,是一个库用于单线程应用程序,另一个库用于多线程应用程序。之所以采用这个设计,是由于标准C运行库是在1970年左右发明的。要在很久很久之后,才会在操作系统上出现线程的概念。标准C运行库的发明者根本没有考虑到为多线程应用程序使用C运行库的问题。让我们用一个例子来了解可能遇到的问题。以标准C运行库的全局变量errno为例。有的函数会在出错时设置该变量。假定现在有这样的一个代码段:BOOL fFailure = (system("NOTEPAD.EXE README.TXT") == -1);if (fFailure) {switch (errno) {case E2BIG: // Argument list or environment too bigbreak;case ENOENT: // Command interpreter cannot be foundbreak;case ENOEXEC: // Command interpreter has bad formatbreak;case ENOMEM: // Insufficient memory to run commandbreak;}}假设在调用了system函数之后,并在执行if语句之前,执行上述代码的线程被中断了。另外还假设,这个线程被中断后,同一个进程中的另一个线程开始执行,而且这个新线程将执行另一个C运行库函数,后者设置了全局变量errno。当CPU后来被分配回第一个线程时,对于上述代码中的system函数调用,errno反映的就不再是正确的错误码。为了解决这个问题,每个线程都需要它自己的errno变量。此外,必须有某种机制能够让一个线程引用它自己的errno变量,同时不能让它去碰另一个线程的errno变量。这仅仅是证明了“标准C/C++运行库最初不是为多线程应用程序而设计”的众多例子中的一个。在多线程环境中会出问题的C/C++运行库变量和函数有errno,_doserrno,strtok,_wcstok,strerror,_strerror,tmpnam,tmpfile,asctime,_wasctime,gmtime,_ecvt和_fcvt等等。为了保证C和C++多线程应用程序正常运行,必须创建一个数据结构,并使之与使用了C/C++运行库函数的每个线程关联。然后,在调用C/C++运行库函数时,那些函数必须知道去查找主调线程的数据块,从而避免影响到其他线程。那么,系统在创建新的线程时,是如何知道要分配这个数据块的呢?答案是它并不知道。系统并不知道应用程序是用C/C++来写的,不知道你调用的函数并非天生就是线程安全的。保证线程安全是程序员的责任。创建新线程时,一定不要调用操作系统的CreateThread函数。相反,必须调用C/C++运行库函数_beginthreadex:unsigned long _beginthreadex(void *security,unsigned stack_size,unsigned (*start_address)(void *),void *arglist,unsigned initflag,unsigned *thrdaddr);_beginthreadex函数的参数列表与CreateThread函数的一样,但是参数名称和类型并不完全一样。这是因为Microsoft的C/C++运行库开发组认为,C/C++运行库函数不应该对Windows数据类型有任何依赖。_beginthreadex函数也会返回新建线程的句柄,就像CreateThread那样。所以,如果已经在自己的源代码中调用了CreateThread函数,可以非常方便地用_beginthreadex来全局替换所有CreateThread。但是,由于数据类型并不完相同,所以可能还必须执行一些类型转换,以便顺利地通过编译。为了简化这个工作,我创建了一个名为chBEGINTHREADEX的宏,并在自己的源代码中使用:typedef unsigned (__stdcall *PTHREAD_START) (void *);#define chBEGINTHREADEX(psa, cbStack, pfnStartAddr, pvParam, fdwCreate, pdwThreadID) ((HANDLE) _beginthreadex( (void *) (psa), (unsigned) (cbStackSize), (PTHREAD_START) (pfnStartAddr), (void *) (pvParam), (unsigned) (dwCreateFlags), (unsigned *) (pdwThreadID)))根据Microsoft为C/C++运行库提供的源代码,很容易看出_beginthreadex能而CreateThread不能做的事情。事实上,在搜索了Visual Studio安装文件夹后,我在<Program Files>Microsoft VisualStudio 8VCcrtsrcThreadex.c中找到了_beginthreadex的源代码。为节省篇幅,这里没有全部照抄一遍。相反,我在这里提供了该函数的伪代码版本,强调了其中最有意思的地方:uintptr_t __cdecl _beginthreadex (void *psa,unsigned cbStackSize,unsigned (__stdcall * pfnStartAddr) (void *),void * pvParam,unsigned dwCreateFlags,unsigned *pdwThreadID) {_ptiddata ptd; // Pointer to thread"s data blockuintptr_t thdl; // Thread"s handle// Allocate data block for the new thread.if ((ptd = (_ptiddata)_calloc_crt(1, sizeof(struct _tiddata))) == NULL)goto error_return;// Initialize the data block.initptd(ptd);// Save the desired thread function and the parameter// we want it to get in the data block.ptd->_initaddr = (void *) pfnStartAddr;ptd->_initarg = pvParam;ptd->_thandle = (uintptr_t)(-1);// Create the new thread.thdl = (uintptr_t) CreateThread((LPSECURITY_ATTRIBUTES)psa, cbStackSize,_threadstartex, (PVOID) ptd, dwCreateFlags, pdwThreadID);if (thdl == 0) {// Thread couldn"t be created, cleanup and return failure.goto error_return;}// Thread created OK, return the handle as unsigned long.return(thdl);error_return:// Error: data block or thread couldn"t be created.// GetLastError() is mapped into errno corresponding values// if something wrong happened in CreateThread._free_crt(ptd);return((uintptr_t)0L);}对于_beginthreadex函数,以下几点需要重点关注。U001000be 每个线程都有自己的专用_tiddata内存块,它们是从C/C++运行库的堆(heap)上分配的。U001000be 传给_beginthreadex的线程函数的地址保存在_tiddata内存块中。(_tiddata结构在Mtdll.h文件的C++源代码中。)纯粹是为了增加趣味性,我在下面重现了这个结构。要传入_beginthreadex函数的参数也保存在这个数据块中。U001000be _beginthreadex确实会在内部调用CreateThread,因为操作系统只知道用这种方式来创建一个新线程。U001000be CreateThread函数被调用时,传给它的函数地址是_threadstartex(而非pfnStartAddr)。另外,参数地址是_tiddata结构的地址,而非pvParam。U001000be 如果一切顺利,会返回线程的句柄,就像CreateThread那样。任何操作失败,会返回0。struct _tiddata {unsigned long _tid; /* thread ID */unsigned long _thandle; /* thread handle */int _terrno; /* errno value */unsigned long _tdoserrno; /* _doserrno value */unsigned int _fpds; /* Floating Point data segment */unsigned long _holdrand; /* rand() seed value */char* _token; /* ptr to strtok() token */wchar_t* _wtoken; /* ptr to wcstok() token */unsigned char* _mtoken; /* ptr to _mbstok() token *//* following pointers get malloc"d at runtime */char* _errmsg; /* ptr to strerror()/_strerror() buff */wchar_t* _werrmsg; /* ptr to _wcserror()/__wcserror() buff */char* _namebuf0; /* ptr to tmpnam() buffer */wchar_t* _wnamebuf0; /* ptr to _wtmpnam() buffer */char* _namebuf1; /* ptr to tmpfile() buffer */wchar_t* _wnamebuf1; /* ptr to _wtmpfile() buffer */char* _asctimebuf; /* ptr to asctime() buffer */wchar_t* _wasctimebuf; /* ptr to _wasctime() buffer */void* _gmtimebuf; /* ptr to gmtime() structure */char* _cvtbuf; /* ptr to ecvt()/fcvt buffer */unsigned char _con_ch_buf[MB_LEN_MAX];/* ptr to putch() buffer */unsigned short _ch_buf_used; /* if the _con_ch_buf is used *//* following fields are needed by _beginthread code */void* _initaddr; /* initial user thread address */void* _initarg; /* initial user thread argument *//* following three fields are needed to support signal handling and runtime errors */void* _pxcptacttab; /* ptr to exception-action table */void* _tpxcptinfoptrs;/* ptr to exception info pointers */int _tfpecode; /* float point exception code *//* pointer to the copy of the multibyte character information used by the thread */pthreadmbcinfo ptmbcinfo;/* pointer to the copy of the locale information used by the thread */pthreadlocinfo ptlocinfo;int _ownlocale; /* if 1, this thread owns its own locale *//* following field is needed by NLG routines */unsigned long _NLG_dwCode;/** Per-Thread data needed by C++ Exception Handling*/void* _terminate; /* terminate() routine */void* _unexpected; /* unexpected() routine */void* _translator; /* S.E. translator */void* _purecall; /* called when pure virtual happens */void* _curexception; /* current exception */void* _curcontext; /* current exception context */int _ProcessingThrow; /* for uncaught_exception */void* _curexcspec; /* for handling exceptions thrown from std::unexpected */#if defined (_M_IA64) || defined (_M_AMD64)void* _pExitContext;void* _pUnwindContext;void* _pFrameInfoChain;unsigned __int64 _ImageBase;#if defined (_M_IA64)unsigned __int64 _TargetGp;#endif /* defined (_M_IA64) */unsigned __int64 _ThrowImageBase;void* _pForeignException;#elif defined (_M_IX86)void* _pFrameInfoChain;#endif /* defined (_M_IX86) */_setloc_struct _setloc_data;void* _encode_ptr; /* EncodePointer() routine */void* _decode_ptr; /* DecodePointer() routine */void* _reserved1; /* nothing */void* _reserved2; /* nothing */void* _reserved3; /* nothing */int _ cxxReThrow; /* Set to True if it"s a rethrown C++ Exception */unsigned long __initDomain; /* initial domain used by _beginthread[ex] for managedfunction */};typedef struct _tiddata * _ptiddata;为新线程分配并初始化_tiddata结构之后,接着应该知道这个结构是如何与线程关联的。来看看_threadstartex函数(它也在C/C++运行库的Threadex.c文件中)。下面是我为这个函数及其helper函数__callthreadstartex编写的伪代码版本:static unsigned long WINAPI _threadstartex (void* ptd) {// Note: ptd is the address of this thread"s tiddata block.// Associate the tiddata block with this thread so// _getptd() will be able to find it in _callthreadstartex.TlsSetValue(__tlsindex, ptd);// Save this thread ID in the _tiddata block.((_ptiddata) ptd)->_tid = GetCurrentThreadId();// Initialize floating-point support (code not shown).// call helper function._callthreadstartex();// We never get here; the thread dies in _callthreadstartex.return(0L);}static void _callthreadstartex(void) {_ptiddata ptd; /* pointer to thread"s _tiddata struct */// get the pointer to thread data from TLSptd = _getptd();// Wrap desired thread function in SEH frame to// handle run-time errors and signal support.__try {// Call desired thread function, passing it the desired parameter.// Pass thread"s exit code value to _endthreadex._endthreadex(( (unsigned (WINAPI *)(void *))(((_ptiddata)ptd)->_initaddr) )( ((_ptiddata)ptd)->_initarg ) ) ;}__except(_XcptFilter(GetExceptionCode(), GetExceptionInformation())){// The C run-time"s exception handler deals with run-time errors// and signal support; we should never get it here._exit(GetExceptionCode());}}关于_threadstartex函数,要注意以下重点:U001000be 新的线程首先执行RtlUserThreadStart (在NTDLL.dll文件中),然后再跳转到_threadstartex。U001000be _threadstartex惟一的参数就是新线程的_tiddata内存块的地址。U001000be TlsSetValue是一个操作系统函数,它将一个值与主调线程关联起来。这就是所谓的线程本地存储(Thread Local Storage,TLS),详情参见第21章。_threadstartex函数将_tiddata内存块与新建线程关联起来。U001000be 在无参数的helper函数_callthreadstartex中,一个SEH帧将预期要执行的线程函数包围起来。这个帧处理着与运行库有关的许多事情——比如运行时错误(如抛出未被捕捉的C++异常)——和C/C++运行库的signal函数。这一点相当重要。如果用CreateThread函数新建了一个线程,然后调用C/C++运行库的signal函数,那么signal函数不能正常工作。U001000be 预期要执行的线程函数会被调用,并向其传递预期的参数。前面讲过,函数的地址和参数由_beginthreadex保存在TLS的_tiddata数据块中;并会在_callthreadstartex中从TLS中获取。U001000be 线程函数的返回值被认为是线程的退出代码。注意_callthreadstartex不是简单地返回到_threadstartex,继而到RtlUserThreadStart;如果是那样的话,线程会终止运行,其退出代码也会被正确设置,但线程的_tiddata内存块不会被销毁。这会导致应用程序出现内存泄漏。为防止出现这个问题,会调用_endthreadex(也是一个C/C++运行库函数),并向其传递退出代码。最后一个需要关注的函数是_endthreadex(也在C运行库的Threadex.c文件中)。下面是我编写的该函数的伪代码版本:void __cdecl _endthreadex (unsigned retcode) {_ptiddata ptd; // Pointer to thread"s data block// Clean up floating-point support (code not shown).// Get the address of this thread"s tiddata block.ptd = _getptd_noexit ();// Free the tiddata block.if (ptd != NULL)_freeptd(ptd);// Terminate the thread.ExitThread(retcode);}对于_endthreadex函数,要注意几下几点:U001000be C运行库的_getptd_noexit函数在内部调用操作系统的TlsGetValue函数,后者获取主调线程的tiddata内存块的地址。U001000be 然后,此数据块被释放,调用操作系统的ExitThread函数来实际地销毁线程。当然,退出代码会被传递,并被正确地设置。在本章早些时候,我曾建议大家应该避免使用ExitThread函数。这是千真万确的,而且我在这里并不打算自相矛盾。前面说过,此函数会杀死主调线程,而且不允许它从当前执行的函数返回。由于函数没有返回,所以构造的任何C++对象都不会被析构。现在,我们又有了不调用ExitThread函数的另一个理由:它会阻止线程的_tiddata内存块被释放,使应用程序出现内存泄漏(直到整个进程终止)。Microsoft的C++开发团队也意识到,总有一些开发人员喜欢调用ExitThread。所以,他们必须使这成为可能,同时尽可能避免应用程序出现内存泄漏的情况。如果真的想要强行杀死自己的线程,可以让它调用_endthreadex(而不是ExitThread)来释放线程的_tiddata块并退出。不过,我并不鼓励你调用_endthreadex。现在,你应该理解了C/C++运行库函数为什么要为每一个新线程准备一个独立的数据块,而且应该理解了_beginthreadex如何分配和初始化此数据块,并将它与新线程关联起来。另外,你还应理解了_endthreadex函数在线程终止运行时是如何释放该数据块的。一旦这个数据块被初始化并与线程关联,线程调用的任何需要“每线程实例数据”的C/C++运行库函数都可以轻易获取主调线程的数据块的地址(通过TlsGetValue),并操纵线程的数据。这对函数来说是没有问题的。但是,对于errno之类的全局变量,它又是如何工作的呢?errno是在标准C headers中定义的,如下所示:_CRTIMP extern int * __cdecl _errno(void);#define errno (*_errno())int* __cdecl _errno(void) {_ptiddata ptd = _getptd_noexit();if (!ptd) {return &ErrnoNoMem;} else {return (&ptd->_terrno);}}任何时候引用errno,实际都是在调用内部的C/C++运行库函数_errno。该函数将地址返回给“与主调线程关联的数据块”中的errno数据成员。注意,errno宏被定义为获取该地址的内容。这个定义是必要的,因为很可能写出下面这样的代码:int *p = &errno;if (*p == ENOMEM) {...}如果内部函数_errno只是返回errno的值,上述代码将不能通过编译。C/C++运行库还围绕特定的函数放置了同步原语(synchronization primitives)。例如,如果两个线程同时调用malloc,堆就会损坏。C/C++运行库函数阻止两个线程同时从内存堆中分配内存。具体的办法是让第2个线程等待,直至第1个线程从malloc函数返回。然后,才允许第2个线程进入。(线程同步将在第8章和第9章详细讨论。)显然,所有这些额外的工作影响了C/C++运行库的多线程版本的性能。C/C++运行库函数的动态链接版本被写得更加泛化,使其可以被使用了C/C++运行库函数的所有运行的应用程序和DLL共享。因此,库只有一个多线程版本。由于C/C++运行库是在一个DLL中提供的,所以应用程序(.exe文件)和DLL不需要包含C/C++运行库函数的代码,所以可以更小一些。另外,如果Microsoft修复了C/C++运行库DLL的任何bug,应用程序将自动获得修复。就像你期望的一样,C/C++运行库的启动代码为应用程序的主线程分配并初始化了一个数据块。这样一来,主线程就可以安全地调用任何C/C++运行库函数。当主线程从其入口函数返回的时候,C/C++运行库函数会释放关联的数据块。此外,启动代码设置了正确的结构化异常处理代码,使主线程能成功调用C/C++运行库的signal函数。6.7.1 用_beginthreadex 而不要用CreateThread 创建线程你可能会好奇,假如调用CreateThread而不是C/C++运行库的_beginthreadex来创建新线程,会发生什么呢?当一个线程调用一个需要_tiddata结构的C/C++运行库函数时,会发生下面的情况。(大多数C/C++运行库函数都是线程安全的,不需要这个结构。)首先,C/C++运行库函数尝试取得线程数据块的地址(通过调用TlsGetValue)。如果NULL被作为_tiddata块的地址返回,表明主调线程没有与之关联的_tiddata块。在这个时候,C/C++运行库函数会为主调线程分配并初始化一个_tiddata块。然后,这个块会与线程关联(通过TlsSetValue) ,而且只要线程还在运行,这个块就会一直存在并与线程关联。现在,C/C++运行库函数可以使用线程的_tiddata块,以后调用的任何C/C++运行库函数也都可以使用。当然,这是相当诱人的,因为线程(几乎)可以顺畅运行。但事实上,问题还是有的。第一个问题是,假如线程使用了C/C++运行库的signal函数,则整个进程都会终止,因为结构化异常处理(SEH)帧没有就绪。第二个问题是,假如线程不是通过调用_endthreadex来终止的,数据块就不能被销毁,从而导致内存泄漏。(对于一个用CreateThread函数来创建的线程,谁会调用_endthreadex呢?)2023-08-10 06:17:225
计算机网络专业术语
adsl[编辑本段]定义 ADSL [1](Asymmetric Digital Subscriber Line )因为上行(用户到电信服务提供商方向,如上传动作)和下行(从电信服务提供商到用户的方向,如下载动作)带宽不对称(即上行和下行的速率不相同)因此称为非对称数字用户线路。它采用频分复用技术把普通的电话线分成了电话、上行和下行三个相对独立的信道,从而避免了相互之间的干扰。通常ADSL在不影响正常电话通信的情况下可以提供最高3.5Mbps的上行速度和最高24Mbps的下行速度。[编辑本段]设备 ADSL[2]是一种异步传输模式(ATM)。 在电信服务提供商端,需要将每条开通ADSL业务的电话线路连接在数字用户线路访问多路复用器(DSLAM)上。而在用户端,用户需要使用一个ADSL终端(因为和传统的调制解调器(Modem)类似,所以也被称为“猫”)来连接电话线路。由于ADSL使用高频信号,所以在两端还都要使用ADSL信号分离器将ADSL数据信号和普通音频电话信号分离出来,避免打电话的时候出现噪音干扰。 通常的ADSL终端有一个电话Line-In,一个以太网口,有些终端集成了ADSL信号分离器,还提供一个连接的Phone接口。 某些ADSL调制解调器使用USB接口与电脑相连,需要在电脑上安装指定的软件以添加虚拟网卡来进行通信。老大,想细致全面的了解麻烦你自己去 百度 百科 查看OK那里面有全面的细致的解说2023-08-10 06:17:412
ⅰmToKen钱包币还可以交易吗
可以。在钱包里买ETH就可以!买USDT交易所交易。2023-08-10 06:17:491
只有im钱包地址和密码怎么付款
不可以付款。imToken钱包明确规定了只有im钱包地址和密码无法付款。mToken冷钱包全球领先的区块链钱包,为千万用户提供可信赖的服务。2023-08-10 06:18:071
浅谈如何选择适合你的区块链钱包?
区块链钱包我是这样认为的现在的数字货币钱包就像是我们平常接触的钱包,很多但是材质不同。如果是货币多的话,建议多几个分散存储,至于选取的话,选大的靠谱的交易方便的。2023-08-10 06:18:173
如何使新浪微博支持SSO授权
sso授权,指的是通过一键点击的简单方式唤起微博客户端行为的授权的方式,因为操作简单,所以作为很多应用的第三方登录的选择。新浪微博下载官方的SDK,在里面有实例和MD5的签名工具。官方SDK在里面的签名工具,根据你输入的包名来得到MD5值,你需要这个值来正确的创建应用。在里面的还有weiboSDK,你需要把它加入你的应用中,引用其中的方法。在清单中加入访问网络的权限需要在新浪的开放平台创建应用。创建应用吧!定义授权参数的接口:(老实说,我是直接copy的demo,改为自己的授权信息就可以了)。[html]viewplaincopyprint?publicinterfaceConstants{/**当前DEMO应用的APP_KEY,第三方应用应该使用自己的APP_KEY替换该APP_KEY*/publicstaticfinalStringAPP_KEY="1608434710";publicstaticfinalStringREDIRECT_URL="";publicstaticfinalStringSCOPE="email,direct_messages_read,direct_messages_write,"+"friendships_groups_read,friendships_groups_write,statuses_to_me_read,"+"follow_app_official_microblog,"+"invitation_write";}缓存授权信息:[html]viewplaincopyprint?/***该类定义了微博授权时所需要的参数。*/publicclassAccessTokenKeeper{privatestaticfinalStringPREFERENCES_NAME="com_weibo_sdk_android";privatestaticfinalStringKEY_UID="uid";privatestaticfinalStringKEY_ACCESS_TOKEN="access_token";privatestaticfinalStringKEY_EXPIRES_IN="expires_in";/***保存Token对象到SharedPreferences。**@paramcontext应用程序上下文环境*@paramtokenToken对象*/publicstaticvoidwriteAccessToken(Contextcontext,Oauth2AccessTokentoken){if(null==context||null==token){return;}SharedPreferencespref=context.getSharedPreferences(PREFERENCES_NAME,Context.MODE_APPEND);Editoreditor=pref.edit();editor.putString(KEY_UID,token.getUid());editor.putString(KEY_ACCESS_TOKEN,token.getToken());editor.putLong(KEY_EXPIRES_IN,token.getExpiresTime());editor.commit();}/***从SharedPreferences读取Token信息。**@paramcontext应用程序上下文环境**@return返回Token对象*/publicstaticOauth2AccessTokenreadAccessToken(Contextcontext){if(null==context){returnnull;}Oauth2AccessTokentoken=newOauth2AccessToken();SharedPreferencespref=context.getSharedPreferences(PREFERENCES_NAME,Context.MODE_APPEND);token.setUid(pref.getString(KEY_UID,""));token.setToken(pref.getString(KEY_ACCESS_TOKEN,""));token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN,0));returntoken;}/***清空SharedPreferences中Token信息。**@paramcontext应用程序上下文环境*/publicstaticvoidclear(Contextcontext){if(null==context){return;}SharedPreferencespref=context.getSharedPreferences(PREFERENCES_NAME,Context.MODE_APPEND);Editoreditor=pref.edit();editor.clear();editor.commit();}}集成的sso授权+获取用户名:[html]viewplaincopyprint?/***该类主要演示如何进行授权、SSO登陆。*/publicclassWBAuthActivityextendsActivityimplementsOnClickListener{/**显示认证后的信息,如AccessToken*/privateTextViewmTokenText;/**微博Web授权类,提供登陆等功能*/privateWeiboAuthmWeiboAuth;/**封装了"access_token","expires_in","refresh_token",并提供了他们的管理功能*/privateOauth2AccessTokenmAccessToken;/**注意:SsoHandler仅当SDK支持SSO时有效*/privateSsoHandlermSsoHandler;/**用户信息接口*/privateUsersAPImUsersAPI;privateButtonssoBtn;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.acy_sinasso);initView();}publicvoidinitView(){mTokenText=(TextView)findViewById(R.id.tv_txt);//SSO授权ssoBtn=(Button)findViewById(R.id.btn_sso);//创建微博实例mWeiboAuth=newWeiboAuth(this,Constants.APP_KEY,Constants.REDIRECT_URL,Constants.SCOPE);//从SharedPreferences中读取上次已保存好AccessToken等信息,//第一次启动本应用,AccessToken不可用mAccessToken=AccessTokenKeeper.readAccessToken(this);2023-08-10 06:18:251
如何使新浪微博支持SSO授权
sso授权,指的是通过一键点击的简单方式唤起微博客户端行为的授权的方式,因为操作简单,所以作为很多应用的第三方登录的选择。当然,你想使用这个功能,首先你得有本地客户端,否则的话,会使用web的授权方式,慢慢的输入你的账户和密码来获取授权。在编码前,你得为此做些简单的准备工作。 1.下载官方的SDK,在里面有实例和MD5的签名工具。官方SDK在里面的签名工具,根据你输入的包名来得到MD5值,你需要这个值来正确的创建应用。在里面的还有weiboSDK,你需要把它加入你的应用中,引用其中的方法。 2.在清单中加入访问网络的权限 3.你需要在新浪的开放平台创建应用。创建应用吧!定义授权参数的接口:(老实说,我是直接copy的demo,改为自己的授权信息就可以了)。[html] view plaincopyprint?public interface Constants { /** 当前 DEMO 应用的 APP_KEY,第三方应用应该使用自己的 APP_KEY 替换该 APP_KEY */ public static final String APP_KEY = "1608434710"; public static final String REDIRECT_URL = "http://www.sina.com"; public static final String SCOPE = "email,direct_messages_read,direct_messages_write," + "friendships_groups_read,friendships_groups_write,statuses_to_me_read," + "follow_app_official_microblog," + "invitation_write"; } 缓存授权信息:[html] view plaincopyprint?/** * 该类定义了微博授权时所需要的参数。 */ public class AccessTokenKeeper { private static final String PREFERENCES_NAME = "com_weibo_sdk_android"; private static final String KEY_UID = "uid"; private static final String KEY_ACCESS_TOKEN = "access_token"; private static final String KEY_EXPIRES_IN = "expires_in"; /** * 保存 Token 对象到 SharedPreferences。 * * @param context 应用程序上下文环境 * @param token Token 对象 */ public static void writeAccessToken(Context context, Oauth2AccessToken token) { if (null == context || null == token) { return; } SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); Editor editor = pref.edit(); editor.putString(KEY_UID, token.getUid()); editor.putString(KEY_ACCESS_TOKEN, token.getToken()); editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime()); editor.commit(); } /** * 从 SharedPreferences 读取 Token 信息。 * * @param context 应用程序上下文环境 * * @return 返回 Token 对象 */ public static Oauth2AccessToken readAccessToken(Context context) { if (null == context) { return null; } Oauth2AccessToken token = new Oauth2AccessToken(); SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); token.setUid(pref.getString(KEY_UID, "")); token.setToken(pref.getString(KEY_ACCESS_TOKEN, "")); token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0)); return token; } /** * 清空 SharedPreferences 中 Token信息。 * * @param context 应用程序上下文环境 */ public static void clear(Context context) { if (null == context) { return; } SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); Editor editor = pref.edit(); editor.clear(); editor.commit(); } } 集成的sso授权 +获取用户名:[html] view plaincopyprint?/** * 该类主要演示如何进行授权、SSO登陆。 */ public class WBAuthActivity extends Activity implements OnClickListener { /** 显示认证后的信息,如 AccessToken */ private TextView mTokenText; /** 微博 Web 授权类,提供登陆等功能 */ private WeiboAuth mWeiboAuth; /** 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能 */ private Oauth2AccessToken mAccessToken; /** 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 */ private SsoHandler mSsoHandler; /** 用户信息接口 */ private UsersAPI mUsersAPI; private Button ssoBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.acy_sinasso); initView(); } public void initView() { mTokenText = (TextView) findViewById(R.id.tv_txt); // SSO 授权 ssoBtn = (Button) findViewById(R.id.btn_sso); // 创建微博实例 mWeiboAuth = new WeiboAuth(this, Constants.APP_KEY, Constants.REDIRECT_URL, Constants.SCOPE); // 从 SharedPreferences 中读取上次已保存好 AccessToken 等信息, // 第一次启动本应用,AccessToken 不可用 mAccessToken = AccessTokenKeeper.readAccessToken(this); if (mAccessToken.isSessionValid()) { updateTokenView(true); } ssoBtn.setOnClickListener(this); } /** * 当 SSO 授权 Activity 退出时,该函数被调用。 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // SSO 授权回调 // 重要:发起 SSO 登陆的 Activity 必须重写 onActivityResult if (mSsoHandler != null) { mSsoHandler.authorizeCallBack(requestCode, resultCode, data); } } /** * 微博认证授权回调类。 1. SSO 授权时,需要在 {@link #onActivityResult} 中调用 * {@link SsoHandler#authorizeCallBack} 后, 该回调才会被执行。 2. 非 SSO * 授权时,当授权结束后,该回调就会被执行。 当授权成功后,请保存该 access_token、expires_in、uid 等信息到 * SharedPreferences 中。 */ class AuthListener implements WeiboAuthListener { // 授权完成 @Override public void onComplete(Bundle values) { // 从 Bundle 中解析 Token mAccessToken = Oauth2AccessToken.parseAccessToken(values); if (mAccessToken.isSessionValid()) { // 显示 Token updateTokenView(false); // 保存 Token 到 SharedPreferences AccessTokenKeeper.writeAccessToken(WBAuthActivity.this, mAccessToken); Toast.makeText(WBAuthActivity.this, "success!!", Toast.LENGTH_SHORT).show(); // 根据uid 获取用户的昵称,因为uid是在回调方法从服务器传递过来的数据中。 long uid = Long.parseLong(mAccessToken.getUid()); mUsersAPI.show(uid, mListener); } else { // 以下几种情况,您会收到 Code: // 1. 当您未在平台上注册的应用程序的包名与签名时; // 2. 当您注册的应用程序包名与签名不正确时; // 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。 Toast.makeText(WBAuthActivity.this, "fail", Toast.LENGTH_LONG) .show(); } } // 取消授权 @Override public void onCancel() { Toast.makeText(WBAuthActivity.this, "cancel", Toast.LENGTH_LONG) .show(); } // 授权异常 @Override public void onWeiboException(WeiboException e) { Toast.makeText(WBAuthActivity.this, "Auth exception : " + e.getMessage(), Toast.LENGTH_LONG) .show(); } } /** * 显示当前 Token 信息。 配置文件中是否已存在 token 信息并且合法 */ public void updateTokenView(boolean hasExisted) { // 获取用户信息接口 mUsersAPI = new UsersAPI(mAccessToken); String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss") .format(new java.util.Date(mAccessToken.getExpiresTime())); String format = getString(R.string.weibosdk_demo_token_to_string_format_1); mTokenText .setText(String.format(format, mAccessToken.getToken(), date)); String message = String.format(format, mAccessToken.getToken(), date); if (hasExisted) { message = getString(R.string.weibosdk_demo_token_has_existed) + " " + message; // 根据uid 获取用户的昵称,因为uid是在回调方法从服务器传递过来的数据中。 long uid = Long.parseLong(mAccessToken.getUid()); mUsersAPI.show(uid, mListener); } mTokenText.setText(message); } /** * 微博 OpenAPI 回调接口。 */ private RequestListener mListener = new RequestListener() { @Override public void onComplete(String response) { if (!TextUtils.isEmpty(response)) { // 调用 User#parse 将JSON串解析成User对象 User user = User.parse(response); if (user != null) { Toast.makeText(WBAuthActivity.this, "获取User信息成功,用户昵称:" + user.screen_name, Toast.LENGTH_LONG).show(); mTokenText.setText(user.screen_name); } else { Toast.makeText(WBAuthActivity.this, response, Toast.LENGTH_LONG).show(); } } } @Override public void onWeiboException(WeiboException e) { ErrorInfo info = ErrorInfo.parse(e.getMessage()); Toast.makeText(WBAuthActivity.this, info.toString(), Toast.LENGTH_LONG).show(); } }; @Override public void onClick(View v) { // TODO Auto-generated method stub if (v == ssoBtn) { mSsoHandler = new SsoHandler(WBAuthActivity.this, mWeiboAuth); mSsoHandler.authorize(new AuthListener()); } } } 布局:[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.sina.weibo.sdk.widget.LoginButton android:id="@+id/btn_sso" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" /> <TextView android:id="@+id/tv_txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="info" /> </LinearLayout>2023-08-10 06:18:332
如何使新浪微博支持SSO授权
sso授权,指的是通过一键点击的简单方式唤起微博客户端行为的授权的方式,因为操作简单,所以作为很多应用的第三方登录的选择。新浪微博下载官方的SDK,在里面有实例和MD5的签名工具。官方SDK在里面的签名工具,根据你输入的包名来得到MD5值,你需要这个值来正确的创建应用。在里面的还有weiboSDK,你需要把它加入你的应用中,引用其中的方法。在清单中加入访问网络的权限需要在新浪的开放平台创建应用。创建应用吧!定义授权参数的接口:(老实说,我是直接copy的demo,改为自己的授权信息就可以了)。[html] view plaincopyprint?public interface Constants { /** 当前 DEMO 应用的 APP_KEY,第三方应用应该使用自己的 APP_KEY 替换该 APP_KEY */ public static final String APP_KEY = "1608434710"; public static final String REDIRECT_URL = "http://www.sina.com"; public static final String SCOPE = "email,direct_messages_read,direct_messages_write," + "friendships_groups_read,friendships_groups_write,statuses_to_me_read," + "follow_app_official_microblog," + "invitation_write"; } 缓存授权信息:[html] view plaincopyprint?/** * 该类定义了微博授权时所需要的参数。 */ public class AccessTokenKeeper { private static final String PREFERENCES_NAME = "com_weibo_sdk_android"; private static final String KEY_UID = "uid"; private static final String KEY_ACCESS_TOKEN = "access_token"; private static final String KEY_EXPIRES_IN = "expires_in"; /** * 保存 Token 对象到 SharedPreferences。 * * @param context 应用程序上下文环境 * @param token Token 对象 */ public static void writeAccessToken(Context context, Oauth2AccessToken token) { if (null == context || null == token) { return; } SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); Editor editor = pref.edit(); editor.putString(KEY_UID, token.getUid()); editor.putString(KEY_ACCESS_TOKEN, token.getToken()); editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime()); editor.commit(); } /** * 从 SharedPreferences 读取 Token 信息。 * * @param context 应用程序上下文环境 * * @return 返回 Token 对象 */ public static Oauth2AccessToken readAccessToken(Context context) { if (null == context) { return null; } Oauth2AccessToken token = new Oauth2AccessToken(); SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); token.setUid(pref.getString(KEY_UID, "")); token.setToken(pref.getString(KEY_ACCESS_TOKEN, "")); token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0)); return token; } /** * 清空 SharedPreferences 中 Token信息。 * * @param context 应用程序上下文环境 */ public static void clear(Context context) { if (null == context) { return; } SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); Editor editor = pref.edit(); editor.clear(); editor.commit(); } } 集成的sso授权 +获取用户名:[html] view plaincopyprint?/** * 该类主要演示如何进行授权、SSO登陆。 */ public class WBAuthActivity extends Activity implements OnClickListener { /** 显示认证后的信息,如 AccessToken */ private TextView mTokenText; /** 微博 Web 授权类,提供登陆等功能 */ private WeiboAuth mWeiboAuth; /** 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能 */ private Oauth2AccessToken mAccessToken; /** 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 */ private SsoHandler mSsoHandler; /** 用户信息接口 */ private UsersAPI mUsersAPI; private Button ssoBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.acy_sinasso); initView(); } public void initView() { mTokenText = (TextView) findViewById(R.id.tv_txt); // SSO 授权 ssoBtn = (Button) findViewById(R.id.btn_sso); // 创建微博实例 mWeiboAuth = new WeiboAuth(this, Constants.APP_KEY, Constants.REDIRECT_URL, Constants.SCOPE); // 从 SharedPreferences 中读取上次已保存好 AccessToken 等信息, // 第一次启动本应用,AccessToken 不可用 mAccessToken = AccessTokenKeeper.readAccessToken(this);2023-08-10 06:18:411
has leaked window android.widget.framelayout怎么解决
我想大多数人,对于这3个东西的概念能区分,但是具体区别在哪却很难说出来。 我这里根据我个人的理解来讲讲我个人对这3个概念的理解。当然这里设计到通用的事件窗口模型等通用GUI设计,我这里就不打算讲了,纯粹从概念上来进行区分。 Activity是Android应用程序的载体,允许用户在其上创建一个用户界面,并提供用户处理事件的API,如onKeyEvent, onTouchEvent等。 并维护应用程序的生命周期(由于android应用程序的运行环境和其他操作系统不同,android的应用程序是运行在框架之内,所以他的应用程序不能当当从进程的级别去考虑,而更多是从概念上去考虑。android应用程序是由多个活动堆积而成,而各个活动又有其独立的生命周期)。Activity本身是个庞大的载体,可以理解成是应用程序的载体,如果木有Activity,android应用将无法运行。也可以理解成android应用程序的入口。Acivity的实例对象由系统维护。系统服务ActivityManager负责维护Activity的实例对象,并根据运行状态维护其状态信息。 但在用户级别,程序员可能根愿意理解成为一个界面的载体。但仅仅是个载体,它本身并不负责任何绘制。Activity的内部实现,实际上是聚了一个Window对象。Window是一个抽象类,它的具体是在android_src_home/framework/policies/base/phone/com/android/internal/policy/impl目录下的PhoneWindow.java。 当我们调用Acitivity的 setContentView方法的时候实际上是调用的Window对象的setContentView方法,所以我们可以看出Activity中关于界面的绘制实际上全是交给Window对象来做的。绘制类图的话,可以看出Activity聚合了一个Window对象。 下面是PhoneWindow中的setContentView方法的实现: @Override public void setContentView(View view, ViewGroup.LayoutParams params) { if (mContentParent == null) { installDecor(); } else { mContentParent.removeAllViews(); } mContentParent.addView(view, params); final Callback cb = getCallback(); if (cb != null) { cb.onContentChanged(); } } Window内部首先判断mContentParent是否为空,然后调用installDecor方法(安装装饰器),我们看看这个方法如何实现的 private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); mDecor.setIsRootNamespace(true); } if (mContentParent == null) { mContentParent = generateLayout(mDecor); mTitleView = (TextView)findViewById(com.android.internal.R.id.title); if (mTitleView != null) { if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) { View titleContainer = findViewById(com.android.internal.R.id.title_container); if (titleContainer != null) { titleContainer.setVisibility(View.GONE); } else { mTitleView.setVisibility(View.GONE); } if (mContentParent instanceof FrameLayout) { ((FrameLayout)mContentParent).setForeground(null); } } else { mTitleView.setText(mTitle); } } } } 在该方法中,首先创建一个DecorView,DecorView是一个扩张FrameLayout的类,是所有窗口的根View。我们在Activity中调用的setConctentView就是放到DecorView中了。这是我们类图的聚合关系如下: Activity--->Window--->DecorView 这是我们得出这3个类之间最直接的一个关系。 我们详细分析一下,类对象是如何被创建的。 先不考虑Activity的创建(因为 Acitivity的实例由ActivityManager维护,是在另一个进程设计到IPC的通信,后面会讲到),而考虑Window和View的创建。 Activity被创建后,系统会调用它的attach方法来将Activity添加到ActivityThread当中。我们找到Activity的attach方法如下: final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance, HashMap<String,Object> lastNonConfigurationChildInstances, Configuration config) { attachBaseContext(context); mWindow= PolicyManager.makeNewWindow(this); mWindow.setCallback(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } mUiThread = Thread.currentThread(); mMainThread = aThread; mInstrumentation = instr; mToken = token; mIdent = ident; mApplication = application; mIntent = intent; mComponent = intent.getComponent(); mActivityInfo = info; mTitle = title; mParent = parent; mEmbeddedID = id; mLastNonConfigurationInstance = lastNonConfigurationInstance; mLastNonConfigurationChildInstances = lastNonConfigurationChildInstances; mWindow.setWindowManager(null, mToken, mComponent.flattenToString()); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config; } 我们看红色的代码部分,就是创建Window对象的代码。感兴趣的同学可以跟踪去看看具体是如何创建的。其实很简单,其内部实现调用了Policy对象的makeNewWindow方法,其方法直接new了一个PhoneWindow对象如下: public PhoneWindow makeNewWindow(Context context) { return new PhoneWindow(context); } 这时我们已经可以把流程串起来,Activity创建后系统会调用其attach方法,将其添加到ActivityThread当中,在attach方法中创建了一个window对象。 下面分析View的创建。我们知道Window聚合了DocerView,当用户调用setContentView的时候会把一颗View树仍给DocerView.View树是已经创建好的实例对象了,所以我们研究的是DocerView是个什么东西,它是如何被创建的。 我们回头看看Window实现里边的setContentView方法,我们看上面代码的红色部分setContentView-> installDecor-> generateDecor. generateDecor直接new了一个DecorView对象: protected DecorView generateDecor() { return new DecorView(getContext(), -1); } 我们可以去看看DecorView的实现,它是PhoneWindow的一个内部类。实现很简单,它默认会包含一个灰色的标题栏,然后在标题栏下边会包含一个空白区域用来当用户调用setContentView的时候放置用户View,并传递事件,这里不做详细分析,感兴趣同学可以自己研究研究。 当DecorView创建好之后再回到Window中的setContentView方法中来,见上面代码蓝色部分,调用 mContentParent.addView(view, params); 来将用户的View树添加到DecorView中。 到这时为止,我想我们已经很清晰的认识到它们3者之间的关系,并知道其创建流程。 现在总结一下: Activity在onCreate之前调用attach方法,在attach方法中会创建window对象。window对象创建时并木有创建Decor对象对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的View 添加到DecorView中。2023-08-10 06:18:501
如何使新浪微博支持SSO授权
sso授权,指的是通过一键点击的简单方式唤起微博客户端行为的授权的方式,因为操作简单,所以作为很多应用的第三方登录的选择。当然,你想使用这个功能,首先你得有本地客户端,否则的话,会使用web的授权方式,慢慢的输入你的账户和密码来获取授权。在编码前,你得为此做些简单的准备工作。1.下载官方的SDK,在里面有实例和MD5的签名工具。官方SDK在里面的签名工具,根据你输入的包名来得到MD5值,你需要这个值来正确的创建应用。在里面的还有weiboSDK,你需要把它加入你的应用中,引用其中的方法。2.在清单中加入访问网络的权限3.你需要在新浪的开放平台创建应用。创建应用吧!定义授权参数的接口:(老实说,我是直接copy的demo,改为自己的授权信息就可以了)。[html] view plaincopyprint?public interface Constants {/** 当前 DEMO 应用的 APP_KEY,第三方应用应该使用自己的 APP_KEY 替换该 APP_KEY */public static final String APP_KEY = "1608434710";public static final String REDIRECT_URL = "http://www.sina.com";public static final String SCOPE ="email,direct_messages_read,direct_messages_write,"+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"+ "follow_app_official_microblog," + "invitation_write"; } 缓存授权信息:[html] view plaincopyprint?/*** 该类定义了微博授权时所需要的参数。*/ public class AccessTokenKeeper {private static final String PREFERENCES_NAME = "com_weibo_sdk_android";private static final String KEY_UID = "uid";private static final String KEY_ACCESS_TOKEN = "access_token";private static final String KEY_EXPIRES_IN = "expires_in";/*** 保存 Token 对象到 SharedPreferences。** @param context 应用程序上下文环境* @param token Token 对象*/public static void writeAccessToken(Context context, Oauth2AccessToken token) {if (null == context || null == token) {return;}SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);Editor editor = pref.edit();editor.putString(KEY_UID, token.getUid());editor.putString(KEY_ACCESS_TOKEN, token.getToken());editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime());editor.commit();}/*** 从 SharedPreferences 读取 Token 信息。** @param context 应用程序上下文环境** @return 返回 Token 对象*/public static Oauth2AccessToken readAccessToken(Context context) {if (null == context) {return null;}Oauth2AccessToken token = new Oauth2AccessToken();SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);token.setUid(pref.getString(KEY_UID, ""));token.setToken(pref.getString(KEY_ACCESS_TOKEN, ""));token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0));return token;}/*** 清空 SharedPreferences 中 Token信息。** @param context 应用程序上下文环境*/public static void clear(Context context) {if (null == context) {return;}SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND);Editor editor = pref.edit();editor.clear();editor.commit();} } 集成的sso授权 +获取用户名:[html] view plaincopyprint?/*** 该类主要演示如何进行授权、SSO登陆。*/ public class WBAuthActivity extends Activity implements OnClickListener {/** 显示认证后的信息,如 AccessToken */private TextView mTokenText;/** 微博 Web 授权类,提供登陆等功能 */private WeiboAuth mWeiboAuth;/** 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能 */private Oauth2AccessToken mAccessToken;/** 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 */private SsoHandler mSsoHandler;/** 用户信息接口 */private UsersAPI mUsersAPI;private Button ssoBtn;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.acy_sinasso);initView();}public void initView() {mTokenText = (TextView) findViewById(R.id.tv_txt);// SSO 授权ssoBtn = (Button) findViewById(R.id.btn_sso);// 创建微博实例mWeiboAuth = new WeiboAuth(this, Constants.APP_KEY,Constants.REDIRECT_URL, Constants.SCOPE);// 从 SharedPreferences 中读取上次已保存好 AccessToken 等信息,// 第一次启动本应用,AccessToken 不可用mAccessToken = AccessTokenKeeper.readAccessToken(this);if (mAccessToken.isSessionValid()) {updateTokenView(true);}ssoBtn.setOnClickListener(this);}/*** 当 SSO 授权 Activity 退出时,该函数被调用。*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// SSO 授权回调// 重要:发起 SSO 登陆的 Activity 必须重写 onActivityResultif (mSsoHandler != null) {mSsoHandler.authorizeCallBack(requestCode, resultCode, data);}}/*** 微博认证授权回调类。 1. SSO 授权时,需要在 {@link #onActivityResult} 中调用* {@link SsoHandler#authorizeCallBack} 后, 该回调才会被执行。 2. 非 SSO* 授权时,当授权结束后,该回调就会被执行。 当授权成功后,请保存该 access_token、expires_in、uid 等信息到* SharedPreferences 中。*/class AuthListener implements WeiboAuthListener {// 授权完成@Overridepublic void onComplete(Bundle values) {// 从 Bundle 中解析 TokenmAccessToken = Oauth2AccessToken.parseAccessToken(values);if (mAccessToken.isSessionValid()) {// 显示 TokenupdateTokenView(false);// 保存 Token 到 SharedPreferencesAccessTokenKeeper.writeAccessToken(WBAuthActivity.this,mAccessToken);Toast.makeText(WBAuthActivity.this, "success!!",Toast.LENGTH_SHORT).show();// 根据uid 获取用户的昵称,因为uid是在回调方法从服务器传递过来的数据中。long uid = Long.parseLong(mAccessToken.getUid());mUsersAPI.show(uid, mListener);} else {// 以下几种情况,您会收到 Code:// 1. 当您未在平台上注册的应用程序的包名与签名时;// 2. 当您注册的应用程序包名与签名不正确时;// 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。Toast.makeText(WBAuthActivity.this, "fail", Toast.LENGTH_LONG).show();}}// 取消授权@Overridepublic void onCancel() {Toast.makeText(WBAuthActivity.this, "cancel", Toast.LENGTH_LONG).show();}// 授权异常@Overridepublic void onWeiboException(WeiboException e) {Toast.makeText(WBAuthActivity.this,"Auth exception : " + e.getMessage(), Toast.LENGTH_LONG).show();}}/*** 显示当前 Token 信息。 配置文件中是否已存在 token 信息并且合法*/public void updateTokenView(boolean hasExisted) {// 获取用户信息接口mUsersAPI = new UsersAPI(mAccessToken);String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new java.util.Date(mAccessToken.getExpiresTime()));String format = getString(R.string.weibosdk_demo_token_to_string_format_1);mTokenText.setText(String.format(format, mAccessToken.getToken(), date));String message = String.format(format, mAccessToken.getToken(), date);if (hasExisted) {message = getString(R.string.weibosdk_demo_token_has_existed)+ " " + message;// 根据uid 获取用户的昵称,因为uid是在回调方法从服务器传递过来的数据中。long uid = Long.parseLong(mAccessToken.getUid());mUsersAPI.show(uid, mListener);}mTokenText.setText(message);}/*** 微博 OpenAPI 回调接口。*/private RequestListener mListener = new RequestListener() {@Overridepublic void onComplete(String response) {if (!TextUtils.isEmpty(response)) {// 调用 User#parse 将JSON串解析成User对象User user = User.parse(response);if (user != null) {Toast.makeText(WBAuthActivity.this,"获取User信息成功,用户昵称:" + user.screen_name,Toast.LENGTH_LONG).show();mTokenText.setText(user.screen_name);} else {Toast.makeText(WBAuthActivity.this, response,Toast.LENGTH_LONG).show();}}}@Overridepublic void onWeiboException(WeiboException e) {ErrorInfo info = ErrorInfo.parse(e.getMessage());Toast.makeText(WBAuthActivity.this, info.toString(),Toast.LENGTH_LONG).show();}};@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (v == ssoBtn) {mSsoHandler = new SsoHandler(WBAuthActivity.this, mWeiboAuth);mSsoHandler.authorize(new AuthListener());}} } 布局:[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><com.sina.weibo.sdk.widget.LoginButtonandroid:id="@+id/btn_sso"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp" /><TextViewandroid:id="@+id/tv_txt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="info" /></LinearLayout>2023-08-10 06:18:581
北部湾集结号在上海市博会展出了吗
没有。《北部湾集结号》的横空出世犹如一剂强心剂,传销组织抓住这根救命稻草疯狂鼓噪,为他们“行业”的合法性正名。正版书的威力确实厉害,效果立竿见影,来考察的新人络容绎不绝,很多传销体系发展迅猛,传销网头们借着这本书赚得盆满钵溢。《北部湾集结号》已进定性为非法出版物。是广西1040阳光工程给新人洗脑用的道具之一。上海世博会也并没有展览这本书,千万不要相信传销分子,遇到这种情况最好赶紧离开,先脱离传销环境。不要自己被传销洗脑了。扩展资料:2005年8月10日国务院第101次常务会议通过的文件《禁止传销条例》,自2005年11月1日起施行。2009年2月28日,为了更有效地打击传销违法犯罪活动,十一届全国人大常委会第七次会议表决通过的刑法修正案(七)增设了“组织领导传销罪”。在刑法第二百二十四条后增加一条,作为第二百二十四条之一:“组织、领导以推销商品、提供服务等经营活动为名,要求参加者以缴纳费用或者购买商品、服务等方式获得加入资格。2023-08-10 06:20:261
北部湾集结号有什么内含吗?它集结的是什么?
北部湾的集结号,它是有内含的。它主要的目地就是宣传推广国家于98年引进的一个项目。如今13年过去了,这个项目现在运行的如何呢?这个项目成就了多少人?又毁灭了多少人的梦想呢? 腾讯号↓↓↓↓↓↓↓〖异〗 8〖地〗 5〖出〗 9〖局〗 1〖老〗 4〖总〗 4〖深〗 1〖度〗 3〖讲〗 6〖解〗2023-08-10 06:20:432
广西北部湾集结号
所谓的北部湾集结号就是非法传销人员编造的忽悠人做下线的资料,但是骗人的。传销是违法行为,大家千万不要上当!2023-08-10 06:20:517
北部湾集结号这本书是什么意思
川流不息的中国经济浪潮,将北部湾推向改革前沿,北部湾风生水起,矗立在中国经济改革的聚光灯下。 北`部`湾地处在东`盟经`济圈和我国华`南经`济`圈、西`南经济圈的结合部,区位优势极其明显,是我国经济发展的战略要地。2008年间,胡`主`席、温`总`理等国`家领`导人先后来到广`西`北`部湾考察,中`共`中`央`总`书`记、国`家`主`席`胡`锦`涛`强`调:“在工作中要解`放思`想,开拓创新,抓住机遇,加快发展”、“要把北`部`湾经`济区(广`西)发展成为经济增长新的一极”、“这篇文章会做得很大,前景广阔”。国`务`院总`理温`家`宝说:“这是一篇大文章,也是一个重要的战略问题。”温`家`宝指示:“要坚持改`革创`新,完善经济区开放开发的体制机制的创新”、要把`北`部`湾建设成为“广`西科学发展的排头兵、率先发展的先行区、改`革开放的试`验`田”。 然而,改`革发展的道路困`难重`重。北`部`湾在前进过程中的每一步都充满艰`辛。经`济改`革是一场观`念的革`命。北`部`湾高举“快速反应”旗`帜,遵照国家领导人的批示,先行先试,开创以商`招商的先河,产生了由一个外商带来几个外商,一个项目引进几个项目的“雁`阵效应”。北`部`湾风`生`水`起涛声阵阵,实`践检验证明,政通人和,改革创新取得了巨大的成果。 《北`部`湾`集`结`号》不是告诉人们改`革开放后中国发生了什么,北`部`湾发生了什么,而是告诉人们面对新`生`事`物如何站在国`家的角度进行思考。关注细节,认真思索,快速反应,严格推理,有经济学原理、关联经济理论经济现象。对研究北`部`湾经济的开放开发具有不容忽视的重要参考价值。2023-08-10 06:21:072
北部湾集结号图书内容
北部湾集结号开头的一段话:在祖国大陆上正发生一场没有硝烟的战争,一支不穿军装的军队,一所没有围墙的大学,一个打造亿万富翁的摇篮,吸引了成千上万的有志之士。他们在媒体的掩护下、忍辱负重、积极运作、成功的构筑着祖国的经济长城。此书主要是讲了中国“黄金十年”的东盟贸易圈,然后讲诉了北部湾中各大城市与地级市、镇等历史及现状最主要的内容就是讲诉了,北部湾在东盟10+1中扮演了什么样的角色和政府开发全中国十四个沿海城市的最后一个处女地的原因和所处这块地方的重要性。2023-08-10 06:21:152
《北部湾结集号》是什么书籍?
《北部湾结集号》听说是一本禁书,我们来看看 。广西某出版社出版的《北部湾集结号》一书内竟刊载有一篇专门为“资本运作”宣传的《资本运作是民间资本投资西部的最佳方式》的文章。该书在我区南宁、北海等地的图书市场销售火爆《北部湾集结号》作者王彬2023-08-10 06:21:222
北部湾集结号西部大开发讲解
北部湾(英文名称:Beibu Gulf),是中国广东雷州半岛、海南岛和广西壮族自治区及越南之间的海湾,全部在大陆架上。大陆架宽约260里,水深由岸边向中央部分逐渐加深,最深处达80公尺;面积接近13万平方公里,比渤海面积略大。平均水深42米,最深达100米。有南流江、红河等注入,由于沿岸河流不多,带入海湾中的泥沙较少。冬季及夏季表层水温相差10℃以上。鱼类以暖水性种类为主,是捕捞绯鲤、红笛鲷、金线鱼、蓝圆鲹等鱼类的优良渔场。主要港口有中国湛江港、防城港,钦州港和北海港以及越南的边水、海防。 折叠编辑本段自然环境 折叠海底地貌 北部湾三面为陆地环抱,水深在10~60米,海底比较单纯,从湾顶向湾口逐渐下降,海底较平坦,从陆地带来的泥沙沉积在上面。属于新生代的大型沉积盆地,沉积层厚达数千米,蕴藏丰富的石油和天然气资源。 折叠气候类型 北部湾地处热带和亚热带,冬季受大陆冷空气的影响,多东北风,海面气温约20℃;夏季,风从热带海洋上来,多西南风,海面气温高达30℃,时常受到台风的袭击,一般每年约有5次台风经过这里。 折叠洋流水温 北部湾的海流,在冬季沿反时针方向转,外海的水沿湾的北部湾风景东侧北上,湾内的水顺着湾的西边南下,形成一个环流;夏季,因西南季风的推动,海流形成一个方向相反的环流。这里,1天内只有一次潮水涨落,叫全日潮。涨落的潮差,从湾口向湾顶逐步增大,在北海附近海域,最大潮差可达7米。潮流大体上沿着海岸方向,一来一去地流淌,这叫往复流。年平均水温高达24.5℃。 折叠沿岸河流 有南流江、红河等注入。 折叠编辑本段自然资源 北部湾风景北部湾的资源丰富,因饵料丰富,盛产鲷鱼、金线鱼、沙丁鱼、竹英鱼、蓝圆鲹、金枪鱼、比目鱼、鲳鱼、鲭鱼等50余种有经济价值的鱼类,及虾、蟹、贝类等,是我国优良的渔场之一。沿岸浅海和滩涂广阔,是发展海水养殖的优良场所,贝类有牡蛎、珍珠贝、日月贝、泥蚶、文蛤等,驰名中外的合浦珍珠(又称南珠)就产在这里。涠洲岛、莺歌海等海底石油、天然气资源也很可观。沿岸河口地区有许多红树林。[1] 折叠编辑本段战略地位 北部湾是我国大西南地区出海口最近的通路。其中湛江港素以天然深水良港著称,是中国大陆通往东南亚、非洲、欧洲和大洋洲航程最短的港口,是中国大西南和华南地区货物的出海主通道,是全国20个沿海主要枢纽港之一,现已与世界100多个国家和地区通航。 重要城市 北部湾位于北部湾畔的我国港口城市有广东的湛江、广西的北海、钦州、防城港等,都是重要的港口城市。广西北部湾经济区处于北部湾顶端的中心位置,主要包括南宁市、北海市、钦州市、防城港市所辖区域范围,同时包括内陆城市玉林市、崇左市的交通和物流。 边界划定 到了2006年,中越北部湾海上边界问题终于解决,专属经济区和领海基线已确定,中国和越南签订协议,划分了北部湾的领海和专属经济区,使得北部湾地区的边界纠纷不复存在。 折叠法定边界 北部湾北部湾(越南称东京湾),北部湾是我国大西南的海上通道,油气和海洋生物资源丰富,也是著名渔场。 上世纪70年代以前,北部湾没有划界,两国渔民不分彼此在北部湾共同劳动。但70年代后期,中越关系恶化,由于中国渔民的捕捞装备较好,越南明显处于下风,于是越方开始采取控制措施,有时甚至开枪射击、武装没收中国渔船。90年代以后,中越关系好转,但双方渔民纠纷仍然不断,越南屡次没收中国渔船。 1974年,中越两国开始就北部湾划界举行谈判,特别是两国关系正常化、1999年两国签署陆地边界条约后,这项谈判进程加快。2000年12月25日,两国签署了《中华人民共和国和越南社会主义共和国关于两国在北部湾领海、专属经济区和大陆架的划界协定》。该协定除序言和约尾外,共有11条,其中第一条确认了双方划分北部湾的法律根据,并明确了本协定的划界范围;第二条至第五条确定了以21个界点划定两国在北部湾的领海、专属经济区和大陆架的分界线;协议还明确了对跨界油气资源和其他矿藏进行开发,以及对生物资源养护利用等事项的合作原则。两国立法机构先后批准了这一协定,标志着中越在北部湾的海上边界已然划定。 划界与渔业问题关系密切 渔业纠纷是中越两国在北部湾的重要争端,因而除划界外,渔业安排也是北部湾边界谈判的重要内容。两国对划界和渔业问题采取捆绑解决的方式,以寻求双方利益的妥协点,因而《中越北部湾渔业合作协定》与《北部湾划界协定》同时签署。《北部湾划界协定》生效后,《渔业合作协定》生效的条件已趋成熟。 这些协定的签订,有利于中越两国边界的稳定和北部湾地区的长治久安,有利于进一步推动中越两国关系的健康发展,符合中国的根本利益。但大量渔船要从传统作业渔场撤出,仍将对我国琼桂粤三省区渔业生产带来影响。过去广东有6000多艘渔船在北部湾西面海域作业,如今则要退回北部湾东部海域作业;海南省59%的渔船在北部湾海域作业,根据《渔业合作协定》,海南省计划从2003年起每年淘汰570艘渔船,转业渔民1.2万人,2002年至2006年将淘汰报废2471艘渔船。为应对这种变化,国家已制定渔民转产计划,拨专款资助部分渔民上岸转业。2023-08-10 06:21:311
ISBN978-7-219-06886-1/F-823请问这本书的刊号是什么书。
北部湾集结号纪念版书名北部湾集结号定价43.00出版社广西人民出版社出版时间2010年2月ISBN9787219068861页数88页王彬编著--南宁:广西人民出版社北部湾集结号ISBN编号:978-7-219-06886-1出版时间:2010年2月 第一版出版社:广西人民出版社页数:88页全彩版次印次:第一版第一次印刷定价:43.002023-08-10 06:21:423
广西北部湾集结号寓意在哪?
单从集结字面理解,也就是激活北部湾外来投资,因此引来更多的人气,加快北部湾资本市场流通,这个行业主要靠人际网络发展,类似美国金字塔式运作模式,以北海为例,从事这个行业就在20万以上,具体是不是国家宏观调控,是不是国家投放政策,谁也不清楚!2023-08-10 06:21:491
北部湾集结号电子版
1、目前北部湾集结号电子版的书是没有的,只能去书店买实体书,在淘宝网,当当网、亚马逊都有卖。定价是43元/本。作者:王彬,2010年2月 第一版,88页全彩2、北部湾集结号由广西人民出版社出版,是一本介绍北部湾迅猛发展的书,是具有智慧的有志之士们不看后悔的一本书,是继珠三角、长三角、环渤海湾三大沿海增长极形成后我国的经济版图又一新的增长极,它将是继香港、深圳和上海浦东后又一耀眼的国际商贸中心。国家主席胡锦涛指出:“要把北部湾经济区(广西)发展成为经济增长新的一级。”北部湾将会成为亚洲经济腾飞的“首都”2023-08-10 06:21:572
北部湾集结号是什么?
是一本非法出版物。借助广西北部湾开发这一题材进行虚假宣传,以介绍人员到南宁买房、投资为名,通过亲戚关系或朋友关系,不断拉拢他人来南宁“考察”,最后“影响”和“感化”不明真相的群众加入到传销组织。2023-08-10 06:22:182
北部湾集结号是不是正版书
的确是正版书,这本书在上海世博会上展览过的,只能看,不许翻阅,里面浓缩的都是精华2023-08-10 06:22:274
上海新升半导体科技有限公司招聘信息,上海新升半导体科技有限公司怎么样?
钉钉企典数据来源于企业征信机构,包含企业风险数据,公司官网,公司简介,更多公司招聘信息详询公司官网,更多公司电话地址企业邮箱可在钉钉企典进行查询u2022 公司简介: 上海新升半导体科技有限公司成立于2014-06-04,注册资本78000.00万人民币元,法定代表人是李炜,公司地址是浦东新区泥城镇新城路2号24幢C1350室,统一社会信用代码与税号是91310115301484416G,行业是其他未列明零售业,登记机关是浦东新区市场监管局,经营业务范围是高品质半导体硅片研发、生产和销售,从事货物及技术的进出口业务。【依法须经批准的项目,经相关部门批准后方可开展经营活动】,上海新升半导体科技有限公司工商注册号是310115002336808 u2022 对外投资: 上海新傲科技股份有限公司,法定代表人是李炜,出资日期是2001-07-25,企业状态是在营(开业),注册资本是31500.00万,出资比例是4.76% u2022 股东: 上海硅产业集团股份有限公司,出资比例98.50%,认缴出资额是76830.000000万上海新阳半导体材料股份有限公司,出资比例1.50%,认缴出资额是1170.000000万 u2022 高管人员: 瞿红珍在公司任职监事徐彦芬在公司任职监事全秀莲在公司任职监事邱慈云在公司任职董事兼总经理李炜在公司任职董事长梁云龙在公司任职董事2023-08-10 06:10:411
中芯国际是私营还是国营企业
中芯国际是股份制上市公司。中芯国际集成电路制造有限公司("中芯国际",纽交所代号:SMI,港交所股份代号:981),是世界领先的集成电路芯片代工企业之一,也是中国内地规模最大、技术最先进的集成电路芯片制造企业。主要业务是根据客户本身或第三者的集成电路设计为客户制造集成电路芯片。中芯国际是纯商业性集成电路代工厂,提供 0.35微米到28纳米制程工艺设计和制造服务。荣获《半导体国际》杂志颁发的"2003年度最佳半导体厂"奖。截止2009年5月,中芯国际已在上海建有一座300mm芯天津厂片厂和三座200mm芯片厂,在北京建有两座300mm芯片厂,在天津建有一座200mm芯片厂,在深圳有一座200mm芯片厂在兴建中,在成都拥有一座封装测试厂。中芯国际还在美国、欧洲、日本提供客户服务和设立营销办事处,同时在香港设立了代表处。此外代武汉新芯集成电路制造有限公司经营管理一座300mm芯片厂。中芯国际自创建以来,已经成长为中国大陆规模最大、技术水准最高,世界排名第四的晶片代工企业。2009年11月10日,中芯国际CEO张汝京因"个人理由"宣布辞职,公司正式进入了"后张汝京时代"。2010年公司继上市当年后首次实现了年度盈利并且收入额创历史新高,在现任总裁兼首席执行长邱慈云的带领下,中芯国际将着重强化生产运营能力、客户服务能力、技术研发能力和市场竞争力,同时发展长期战略合作客户,走进稳定、发展及战略竞争的新纪元。中芯国际向全球客户提供0.35微米到45/40纳米芯片代工与技术服务。除了中芯国际高端的制造能力之外,我们为客户提供全方位的晶圆代工解决方案,以一站式服务满足客户的不同需求:从光罩制造、IP研发及后段辅助设计服务到外包服务(包含凸块服务、晶圆片探测,以及最终的封装、终测等)。全面一体的晶圆代工解决方案务求能最有效缩短产品上市时间,同时最大降低成本。公司与世界级设计服务、智能模块、标准单元库以及EDA工具提供商建立了合作伙伴关系,为客户提供广泛且高灵活度的设计支持。公司装备了大陆最先进的光掩膜生产线,技术能力跨越0.5微米到45纳米。我们的测试服务则针对逻辑电路、存储器、混合信号电路等多种芯片。为了更好地服务全球客户,中芯国际还在美国、欧洲、日本和台湾地区提供客户服务和设立营销办事处。作为提供高品质服务的一部分,中芯国际在上海的所有工厂在试产7个月内上海中芯国际均以零缺陷率通过ISO9001认证。中芯国际的环保措施也获得了ISO14001认证,员工安全卫生体系获得了OHSAS18001认证。另外,中芯国际还取得了ISO/TS16949汽车业器件质量认证和TL9000电信业产品品质及可靠性质量管理体系认证。2023-08-10 06:10:233
中芯国际是私营还是国营企业?
中芯国际属于股份制上市公司。中芯国际集成电路制造有限公司(“中芯国际”,纽交所代号:SMI,港交所股份代号:981),是世界领先的集成电路芯片代工企业之一,也是中国内地规模最大、技术最先进的集成电路芯片制造企业。中芯国际是纯商业性集成电路代工厂,提供 0.35微米到28纳米制程工艺设计和制造服务。荣获《半导体国际》杂志颁发的"2003年度最佳半导体厂"奖项。扩展资料中芯国际向全球客户提供0.35微米到45/40纳米芯片代工与技术服务。除了中芯国际高端的制造能力之外,我们为客户提供全方位的晶圆代工解决方案,以一站式服务满足客户的不同需求:从光罩制造、IP研发及后段辅助设计服务到外包服务(包含凸块服务、晶圆片探测,以及最终的封装、终测等)。全面一体的晶圆代工解决方案务求能最有效缩短产品上市时间,同时最大降低成本。公司与世界级设计服务、智能模块、标准单元库以及EDA工具提供商建立了合作伙伴关系,为客户提供广泛且高灵活度的设计支持。公司装备了大陆最先进的光掩膜生产线,技术能力跨越0.5微米到45纳米。我们的测试服务则针对逻辑电路、存储器、混合信号电路等多种芯片。为了更好地服务全球客户,中芯国际还在美国、欧洲、日本和台湾地区提供客户服务和设立营销办事处。参考资料来源:百度百科-中芯国际2023-08-10 06:09:552
中芯国际是国企吗还是台企?
中芯国际是外企。中芯国际全称为中芯国际集成电路制造有限公司,它属于外国法人独资企业,所以属于外企。它是世界领先的集成电路晶圆代工企业之一,也是中国内地技术最先进、配套最完善、规模最大、跨国经营的集成电路制造企业。中芯国际的经营范围有半导体(硅片及各类化合物半导体)集成电路芯片制造、针测及测试,与集成电路有关的开发、设计服务、技术服务、光掩膜制造、测试封装,销售自产产品。简介现在中芯国际在上海建有一座300mm晶圆厂和一座200mm晶圆厂;在北京建有一座300mm晶圆厂和一座控股的300mm先进制程晶圆厂。在天津和深圳各建有一座200mm晶圆厂;在江阴有一座控股的300mm凸块加工合资厂。以上内容参考:百度百科-中芯国际控股有限公司2023-08-10 06:09:233
中芯国际是外企为什么总说中国芯?
因为第一大股东为国资。在芯片行业,国外对中国的限制是非常大的,不管是对中国的限制还是中国企业的限制,他们都有相关的协定。因此,中国高科技企业只有两条路可以走,第一是完全性的自主研发,即通过这种方式去突破相关的技术封锁。第二就是在外国建立公司,例如开曼群岛等等,然后再国资入场进行收购。扩展资料中芯国际是外企的原因还是因为国外对中国的禁令导致的,一方面冷战结束之后,西方国家在美国的主导下签署了《瓦森纳协定》,这个协定限制了先进材料、电子器件、军品等各种商品或技术的出口。而我们就是禁运国家。另一方面中芯国际本身只有是外资企业才能购买相关设备和技术,不然拿不到美国的出口许可。中芯国际向全球客户提供0.35微米到45/40纳米芯片代工与技术服务。除了中芯国际高端的制造能力之外,我们为客户提供全方位的晶圆代工解决方案,以一站式服务满足客户的不同需求:从光罩制造、IP研发及后段辅助设计服务到外包服务(包含凸块服务、晶圆片探测,以及最终的封装、终测等)。全面一体的晶圆代工解决方案务求能最有效缩短产品上市时间,同时最大降低成本。参考资料来源:百度百科—中芯国际2023-08-10 06:08:458
中芯国际是怎样的一家公司
中芯国际集成电路制造有限公司,是一家中国内地规模最大、技术最先进的集成电路芯片制造企业。主要业务是根据客户本身或第三者的集成电路设计为客户制造集成电路芯片。中芯国际是纯商业性集成电路代工厂,提供 0.35微米到14纳米制程工艺设计和制造服务。荣获《半导体国际》杂志颁发的"2003年度最佳半导体厂"奖项。2020年7月,2020年《财富》中国500强排行榜发布,中芯国际集成电路制造有限公司排名第427位。扩展资料:现有规模:截止2009年5月,中芯国际已在上海建有一座300mm芯片厂和三座200mm芯片厂,在北京建有两座300mm芯片厂,在天津建有一座200mm芯片厂,在深圳有一座200mm芯片厂在兴建中,在成都拥有一座封装测试厂。中芯国际还在美国、欧洲、日本提供客户服务和设立营销办事处,同时在香港设立了代表处。此外代武汉新芯集成电路制造有限公司经营管理一座300mm芯片厂。中芯国际自创建以来,已经成长为中国大陆规模最大、技术水准最高,世界排名第四的晶片代工企业。2009年11月10日,中芯国际CEO张汝京因“个人理由”宣布辞职,公司正式进入了“后张汝京时代”。2010年公司继上市当年后首次实现了年度盈利并且收入额创历史新高,在现任总裁兼首席执行长邱慈云的带领下,中芯国际将着重强化生产运营能力、客户服务能力、技术研发能力和市场竞争力,同时发展长期战略合作客户,走进稳定、发展及战略竞争的新纪元。参考资料来源:百度百科-中芯国际2023-08-10 06:08:131
中芯国际是一家什么企业?
中芯国际集成电路制造有限公司于2000年4月3日根据开曼群岛法例注册成立。2004年3月18日于香港联合交易所主板上市。2020年7月16日在上海证券交易所科创板鸣锣上市。中芯国际主要业务是根据客户本身或第三者的集成电路设计为客户制造集成电路芯片。中芯国际是纯商业性集成电路代工厂,提供 0.35微米到14纳米制程工艺设计和制造服务。温馨提示:以上信息仅供参考。应答时间:2021-03-16,最新业务变化请以平安银行官网公布为准。 [平安银行我知道]想要知道更多?快来看“平安银行我知道”吧~ https://b.pingan.com.cn/paim/iknow/index.html2023-08-10 06:07:491
中芯国际是怎样的一家公司?
中芯国际集成电路制造有限公司,是一家中国内地规模最大、技术最先进的集成电路芯片制造企业。主要业务是根据客户本身或第三者的集成电路设计为客户制造集成电路芯片。中芯国际是纯商业性集成电路代工厂,提供 0.35微米到14纳米制程工艺设计和制造服务。荣获《半导体国际》杂志颁发的"2003年度最佳半导体厂"奖项。2020年7月,2020年《财富》中国500强排行榜发布,中芯国际集成电路制造有限公司排名第427位。扩展资料:现有规模:截止2009年5月,中芯国际已在上海建有一座300mm芯片厂和三座200mm芯片厂,在北京建有两座300mm芯片厂,在天津建有一座200mm芯片厂,在深圳有一座200mm芯片厂在兴建中,在成都拥有一座封装测试厂。中芯国际还在美国、欧洲、日本提供客户服务和设立营销办事处,同时在香港设立了代表处。此外代武汉新芯集成电路制造有限公司经营管理一座300mm芯片厂。中芯国际自创建以来,已经成长为中国大陆规模最大、技术水准最高,世界排名第四的晶片代工企业。2009年11月10日,中芯国际CEO张汝京因“个人理由”宣布辞职,公司正式进入了“后张汝京时代”。2010年公司继上市当年后首次实现了年度盈利并且收入额创历史新高,在现任总裁兼首席执行长邱慈云的带领下,中芯国际将着重强化生产运营能力、客户服务能力、技术研发能力和市场竞争力,同时发展长期战略合作客户,走进稳定、发展及战略竞争的新纪元。参考资料来源:百度百科-中芯国际2023-08-10 06:07:301
中芯国际是国企吗还是台企
中芯国际是国企。中芯国际创立之初,属于一家外国法人独资企业,简单来说就是外资企业。随着中芯国际的不断发展壮大,外资、国有资本开始入股中芯国际,经过多年的发展,如今中芯国际的主要股东都是国有资本,外资成分大大降低。截止2009年5月,中芯国际已在上海建有一座300mm芯片厂和三座200mm芯片厂,在北京建有两座300mm芯片厂,在天津建有一座200mm芯片厂,在深圳有一座200mm芯片厂在兴建中,在成都拥有一座封装测试厂。中芯国际还在美国、欧洲、日本提供客户服务和设立营销办事处,同时在香港设立了代表处。此外代武汉新芯集成电路制造有限公司经营管理一座300mm芯片厂。中芯国际自创建以来,已经成长为中国大陆规模最大、技术水准最高,世界排名第四的晶片代工企业。在现任总裁兼首席执行长邱慈云的带领下,中芯国际将着重强化生产运营能力、客户服务能力、技术研发能力和市场竞争力,同时发展长期战略合作客户,走进稳定、发展及战略竞争的新纪元。2023-08-10 06:06:311
上海新升半导体科技有限公司招聘信息,上海新升半导体科技有限公司怎么样?
钉钉企典数据来源于企业征信机构,包含企业风险数据,公司官网,公司简介,更多公司招聘信息详询公司官网,更多公司电话地址企业邮箱可在钉钉企典进行查询u2022 公司简介: 上海新升半导体科技有限公司成立于2014-06-04,注册资本78000.00万人民币元,法定代表人是李炜,公司地址是浦东新区泥城镇新城路2号24幢C1350室,统一社会信用代码与税号是91310115301484416G,行业是其他未列明零售业,登记机关是浦东新区市场监管局,经营业务范围是高品质半导体硅片研发、生产和销售,从事货物及技术的进出口业务。【依法须经批准的项目,经相关部门批准后方可开展经营活动】,上海新升半导体科技有限公司工商注册号是310115002336808 u2022 对外投资: 上海新傲科技股份有限公司,法定代表人是李炜,出资日期是2001-07-25,企业状态是在营(开业),注册资本是31500.00万,出资比例是4.76% u2022 股东: 上海硅产业集团股份有限公司,出资比例98.50%,认缴出资额是76830.000000万上海新阳半导体材料股份有限公司,出资比例1.50%,认缴出资额是1170.000000万 u2022 高管人员: 瞿红珍在公司任职监事徐彦芬在公司任职监事全秀莲在公司任职监事邱慈云在公司任职董事兼总经理李炜在公司任职董事长梁云龙在公司任职董事2023-08-10 06:06:121
上海新升半导体科技有限公司招聘信息,上海新升半导体科技有限公司怎么样?
钉钉企典数据来源于企业征信机构,包含企业风险数据,公司官网,公司简介,更多公司招聘信息详询公司官网,更多公司电话地址企业邮箱可在钉钉企典进行查询u2022 公司简介: 上海新升半导体科技有限公司成立于2014-06-04,注册资本78000.00万人民币元,法定代表人是李炜,公司地址是浦东新区泥城镇新城路2号24幢C1350室,统一社会信用代码与税号是91310115301484416G,行业是其他未列明零售业,登记机关是浦东新区市场监管局,经营业务范围是高品质半导体硅片研发、生产和销售,从事货物及技术的进出口业务。【依法须经批准的项目,经相关部门批准后方可开展经营活动】,上海新升半导体科技有限公司工商注册号是310115002336808 u2022 对外投资: 上海新傲科技股份有限公司,法定代表人是李炜,出资日期是2001-07-25,企业状态是在营(开业),注册资本是31500.00万,出资比例是4.76% u2022 股东: 上海硅产业集团股份有限公司,出资比例98.50%,认缴出资额是76830.000000万上海新阳半导体材料股份有限公司,出资比例1.50%,认缴出资额是1170.000000万 u2022 高管人员: 瞿红珍在公司任职监事徐彦芬在公司任职监事全秀莲在公司任职监事邱慈云在公司任职董事兼总经理李炜在公司任职董事长梁云龙在公司任职董事2023-08-10 06:05:441
中芯国际是国企吗还是台企
中芯国际是国企。中芯国际创立之初,属于一家外国法人独资企业,简单来说就是外资企业。随着中芯国际的不断发展壮大,外资、国有资本开始入股中芯国际,经过多年的发展,如今中芯国际的主要股东都是国有资本,外资成分大大降低。扩展资料截止2009年5月,中芯国际已在上海建有一座300mm芯片厂和三座200mm芯片厂,在北京建有两座300mm芯片厂,在天津建有一座200mm芯片厂,在深圳有一座200mm芯片厂在兴建中,在成都拥有一座封装测试厂。中芯国际还在美国、欧洲、日本提供客户服务和设立营销办事处,同时在香港设立了代表处。此外代武汉新芯集成电路制造有限公司经营管理一座300mm芯片厂。中芯国际自创建以来,已经成长为中国大陆规模最大、技术水准最高,世界排名第四的晶片代工企业。在现任总裁兼首席执行长邱慈云的带领下,中芯国际将着重强化生产运营能力、客户服务能力、技术研发能力和市场竞争力,同时发展长期战略合作客户,走进稳定、发展及战略竞争的新纪元。参考资料来源:百度百科-中芯国际2023-08-10 06:03:481