https://top.np-sys.com/wp-content/uploads/2021/08/logo-1-300x53.png00M. Shikishimahttps://top.np-sys.com/wp-content/uploads/2021/08/logo-1-300x53.pngM. Shikishima2021-07-21 21:19:182021-10-05 10:39:14toDataURL()メソッド利用の際の 「Tainted canvases may not be exported」エラーについて
# coding: utf-8
import os
import io
import time
import string
import random
import datetime
from flask import Flask, render_template, request, redirect, url_for, send_from_directory,send_file
from flask_cors import CORS
import inspect
import pandas as pd
app = Flask(__name__)
CORS(app)
@app.route('/',methods=["GET","POST"])
def hello():
df = pd.DataFrame({'A':[i for i in range(100)]})
a = str(list(df.T.to_dict().values()))
print(a)
return a
if __name__ == "__main__":
pass
#app.run(host='127.0.0.1',debug=True)
Note:please keep in mind that I am not native English speaker.
In this article, I would like to summarize how to insert ads into Ionic (Angular) project using adsense.
Admob is more popular than adsense for Ionic, but Admob does not support web platforms. If you want to deploy your project as a web app, you need to use Adsense instead of Admob.
However, there is little information on how to use Adsense with Angular, let alone Ionic. Therefore, I would like to introduce the steps here in this article.
Summary
Basically, I recommend you to use ng2-adsense plugin, but it doesn’t work even if you implement it according to the instructions on the official page. You need to add some other code. In addition, it is important to have a ad with fixed size(not responsive). If you set your ad style with responsive, it will not work. Lastly, I recommend you to place your ad on the top area for your page. It may sounds nonsense, but it was important to me.
Next, add following codes to the module where you want to place your ad. Officially, it says to add to app.module.ts, but please add it into the module you want to use. For example, add code into home.module.ts as shown below.
Create ad styles in fixed size, not responsive mode (I recommend you to create ad with inline-block; width: 728px; height: 90px).
Add the snippet on top of the ion-content tag.
If you set ad style to responsive, it will not work. If you do not add it to the top of the ion-content tag, it will not work neither. I know it sounds strange, but I think Adsense doesn’t recognize content in Angular page. So I recommend you to do that.
Furthermore, it sounds strange to add the snippet starting with “<script” tag. However, this was also necessary for me to work.
You can check adClient and adSlot and snippet in your adsense page.
To see your snippet, click the <> button at the bottom right of the screen below.
Also, to change the style of your ad from responsive to fixed size, press the pencil mark to fix it from responsive.
As a rule of thumb, to make sure Googlebot finds all views, make sure that:
All links are implemented as <a href="">
All links have a valid URL as their href attribute (no javascript: URLs)
All views have a URL that doesn’t use the fragment identifier to load different content (no URLs like “/#example” or “/#!example“, sometimes called a hash URL)
このファイルを編集するのですが、編集するにはコツが入ります、info.plistの上で右クリックをして、open as > source codeを選択して編集できるようにします。
そして、下記のスニペットを下の方に貼り付けます。自分のアプリIDに変更するのを忘れないでください。
<key>GADIsAdManagerApp</key>
<true/>
<key>GADApplicationIdentifier</key>
<!-- replace this value with your App ID key-->
<string>ca-app-pub-7171076285090910~XXXXXXXX</string>
<application>
<!-- this line needs to be added (replace the value!) -->
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-7171076285090910~XXXXXXXX" />
<activity></activity>
</application>
Projectを選択した状態で、Android>app>src>main>java><your original name>>MainActivityを選択します。
そして、このように変更します。
// Other imports...
import app.xplatform.capacitor.plugins.AdMob;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
add(AdMob.class); // Add AdMob as a Capacitor Plugin
}});
}
}
つまり、このようにします。
package io.ionic.starter;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import java.util.ArrayList;
import app.xplatform.capacitor.plugins.AdMob;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
add(AdMob.class); // Add AdMob as a Capacitor Plugin
}});
}
}
2020-12-21 15:44:03.866 9236-9236/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: io.ionic.starter, PID: 9236
java.lang.RuntimeException: Unable to start activity ComponentInfo{io.ionic.starter/io.ionic.starter.MainActivity}: android.view.InflateException: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Error inflating class android.support.design.widget.CoordinatorLayout
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: android.view.InflateException: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Error inflating class android.support.design.widget.CoordinatorLayout
Caused by: android.view.InflateException: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Error inflating class android.support.design.widget.CoordinatorLayout
Caused by: java.lang.ClassNotFoundException: android.support.design.widget.CoordinatorLayout
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:454)
at android.view.LayoutInflater.createView(LayoutInflater.java:815)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
at android.view.LayoutInflater.inflate(LayoutInflater.java:659)
at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
at com.getcapacitor.BridgeActivity.init(BridgeActivity.java:60)
at com.getcapacitor.BridgeActivity.init(BridgeActivity.java:48)
at io.ionic.starter.MainActivity.onCreate(MainActivity.java:17)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2020-12-21 15:44:03.866 9236-9236/? E/AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.design.widget.CoordinatorLayout" on path: DexPathList[[zip file "/data/app/io.ionic.starter-wIOzWpenwsyjIPlSvEtd-g==/base.apk"],nativeLibraryDirectories=[/data/app/io.ionic.starter-wIOzWpenwsyjIPlSvEtd-g==/lib/x86, /system/lib, /system/product/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 28 more
そこで、この辺を解決してくれるように下記のライブラリを導入します。
terminalで下記を打ちます。
npm install jetifier
npx jetify
npx cap sync android
onButtonClicked(){
this.croppedImageBase64 = this.buffCroppedImageBase64;
console.log(this.croppedImageBase64,'this.croppedImageBase64');
var bin = atob(this.buffCroppedImageBase64.replace(/^.*,/, ''));
// バイナリデータ化
var buffer = new Uint8Array(bin.length);
for (var i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
this.croppedFileObject = new File([buffer.buffer], "heihei.jpg",{type: "image/jpeg"});
console.log(this.croppedFileObject,'this.croppedFileObject');
}
最終的に下記にようにします。
import { Component } from '@angular/core';
import { ImageCroppedEvent } from 'ngx-image-cropper';
import { LoadingController } from '@ionic/angular';
import { Observable } from 'rxjs';
@Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
imageChangedEvent: any = '';
originalImgName:string;
buffCroppedImageBase64:string;
croppedImageBase64: any = '';
show:any=false;
constructor(
public loadingController: LoadingController,
) {}
fileChangeEvent(event: any): void {
console.log(event,'abcde');
this.show = true;
this.read(event).subscribe(()=>{
console.log('done');
this.show = false;
});
}
read(event: any):Observable<any> {
return new Observable(observer => {
setTimeout(() => {
this.imageChangedEvent = event;
this.originalImgName = event.target.files[0].name;
observer.next('e');
}, 500);
})
}
imageCropped(event: ImageCroppedEvent) {
this.buffCroppedImageBase64 = event.base64;
}
imageLoaded(image: HTMLImageElement) {
// show cropper
}
cropperReady() {
// cropper ready
}
loadImageFailed() {
// show message
}
onButtonClicked(){
this.croppedImageBase64 = this.buffCroppedImageBase64;
console.log(this.croppedImageBase64,'this.croppedImageBase64');
var bin = atob(this.buffCroppedImageBase64.replace(/^.*,/, ''));
// バイナリデータ化
var buffer = new Uint8Array(bin.length);
for (var i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
this.croppedFileObject = new File([buffer.buffer], "heihei.jpg",{type: "image/jpeg"});
console.log(this.croppedFileObject,'this.croppedFileObject');
}
}
また、LazyLoadingという最初に全てを読み込むわけではなく、必要なものはあとで読み込む機能を実装しているので、軽量に高速で動作します。LazyLoadingはAngularにも実装されているので迷うかもしれませんが、こちらに英語ですがIonic X AngularにおけるLazy Loadingの実装方法について記事がまとまっています。このように公式が充実しているのもIonicのいいところです。https://ionicframework.com/blog/how-to-lazy-load-in-ionic-angular/
% ionic start
Pick a framework! ?
Please select the JavaScript framework to use for your new app. To bypass this
prompt next time, supply a value for the --type option.
? Framework: Angular
Every great app needs a name! ?
Please enter the full name of your app. You can change this at any time. To
bypass this prompt next time, supply name, the first argument to ionic start.
? Project name: myApp
Now that you’ve started a new membership year, make sure your device list is up to date. Once you complete this process, new devices can be added.
Select the devices you’d like to keep for this membership year and deselect the devices you’d like to remove. Only your currently enabled devices are shown and all previously disabled devices will be removed automatically. To keep a previously disabled device, visit the All Devices page, enable the devices you’d like to keep, and return to this page.
Continueを押下
この画面の「I acknowledge that any devices I disable during this membership year will continue to count towards my total registered devices.」にチェックを入れてResetする。
% ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/masaya/.ssh/id_rsa): /Users/masaya/.ssh/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/masaya/.ssh/id_rsa.
Your public key has been saved in /Users/masaya/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:chw/VNuyHQ9D0DLooAVRfu9KtEK4TXoOVh36Gkw2c9U masaya@local-host
The key's randomart image is:
+---[RSA 3072]----+
| o+. .oo. |
| .o ..o=. |
| ooo+ +oE |
| .o B.+ + = |
| o S * o . .|
| & * + |
| = * + . |
| . + = . |
| o . |
+----[SHA256]-----+
権限を読み取り専用に変更して
chmod 600 id_rsa
情報をコピーして
% pbcopy < ~/.ssh/id_rsa.pub
GitHubに行って、アイコンをクリックしてから「settings」 > 「SSH and GPG keys」 > 「New SSH Key」と進んで、情報を貼り付ける
あとは下記で疎通できることを確認します。
% ssh -T git@github.com
The authenticity of host 'github.com (13.**.40.48)' can't be established.
RSA key fingerprint is SHA256:********pJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,13.***.40.48' (RSA) to the list of known hosts.
Hi N****! You've successfully authenticated, but GitHub does not provide shell access.
% ionic start
Pick a framework! ?
Please select the JavaScript framework to use for your new app. To bypass this
prompt next time, supply a value for the --type option.
? Framework: (Use arrow keys)
❯ Angular | https://angular.io
React | https://reactjs.org
? Project name: my-first-app
Let's pick the perfect starter template! ?
Starter templates are ready-to-go Ionic apps that come packed with everything
you need to build your app. To bypass this prompt next time, supply template,
the second argument to ionic start.
? Starter template: tabs
✔ Preparing directory ./my-first-app in 1.93ms
✔ Downloading and extracting tabs starter in 998.19ms
? Integrate your new app with Capacitor to target native iOS and Android? (y/N)
y
ダウンロードしたら、プロジェクトへ移動します。
% cd my-first-app/
ionic serveコマンドでビルドしてみます。
% ionic serve
> ng run app:serve --host=localhost --port=8100
<pre class="wp-block-syntaxhighlighter-code">RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html</pre>
import {HttpClientModule, HttpClient} from '@angular/common/http';
import {TranslateModule} from '@ngx-translate/core';
・
imports: [
HttpClientModule,
TranslateModule.forRoot(),
],
使いたい場所のモジュール
使いたい場所のモジュールで
import {HttpClientModule, HttpClient} from '@angular/common/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, '../../assets/i18n/', '.json');
}
{
"Main": "メイン",
"File selection": "ファイルの選択",
"1. Choose a file": "1. ファイルの選択",
"Pick a file from your storage": "ストレージから選択",
"Or take a new picture": "新しく写真を撮る",
"2. Crop your image": "2. 写真の切り抜き",
"select the area you want to analyze from the photo": "解析したいエリアを選択してください",
"No ads 3 times if you watch a short video": "広告が3回表示されなくなります!",
"Preparing for the analysis. Since this app uses service that need to be payed(from not you but me), an ad will be shown to you.":"安全な方法でアップロードします。 このアプリは有料のAPIを使用しているため、広告が表示されます。",
"Analyzing.":"分析しています。"
}
いま、スマホアプリって作っても全然インストールしてもらえないんですよね。もう市場飽和してて、10年前ならインストールされたのになんて思いなが開発していました。そんな矢先、Google Play storeからHuaweiが締め出されたという話があり、あっという間に5社で連合で新しいアプリストアが立ち上げられました。App Galleryです。これはチャンスでございます。なので手元のAndroidアプリをApp galleryでリリースしたのでその所感をお伝えします。
Using "requireCordovaModule" to load non-cordova module "path" is not supported. Instead, add this module to your dependencies and use regular "require" to load it.